nektos/act · error

invalid --security-opt: %q

Error message

invalid --security-opt: %q

What it means

parseSecurityOpts accepts --security-opt entries in key=value or key:value form, with the single exception of the valueless 'no-new-privileges'. Any other entry without a value ('seccomp', 'apparmor' alone) or with an empty value ('apparmor=') fails with this error before the container starts.

Source

Thrown at pkg/container/docker_cli.go:944

func parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]string, error) {
	loggingOptsMap := opts.ConvertKVStringsToMap(loggingOpts)
	if loggingDriver == "none" && len(loggingOpts) > 0 {
		return map[string]string{}, fmt.Errorf("invalid logging opts for driver %s", loggingDriver)
	}
	return loggingOptsMap, nil
}

// takes a local seccomp daemon, reads the file contents for sending to the daemon
func parseSecurityOpts(securityOpts []string) ([]string, error) {
	for key, opt := range securityOpts {
		k, v, ok := strings.Cut(opt, "=")
		if !ok && k != "no-new-privileges" {
			k, v, ok = strings.Cut(opt, ":")
		}
		if (!ok || v == "") && k != "no-new-privileges" {
			// "no-new-privileges" is the only option that does not require a value.
			return securityOpts, fmt.Errorf("invalid --security-opt: %q", opt)
		}
		if k == "seccomp" {
			switch v {
			case seccompProfileDefault, seccompProfileUnconfined:
				// known special names for built-in profiles, nothing to do.
			default:
				// value may be a filename, in which case we send the profile's
				// content if it's valid JSON.
				f, err := os.ReadFile(v)
				if err != nil {
					return securityOpts, fmt.Errorf("opening seccomp profile (%s) failed: %w", v, err)
				}
				var b bytes.Buffer
				if err := json.Compact(&b, f); err != nil {
					return securityOpts, fmt.Errorf("compacting json for seccomp profile (%s) failed: %w", v, err)
				}
				securityOpts[key] = "seccomp=" + b.String()
			}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Give the option a value: --security-opt seccomp=unconfined or --security-opt apparmor=docker-default
  2. Spell the valueless option exactly: --security-opt no-new-privileges
  3. Check YAML for keys whose value was dropped (key: with nothing after)

Example fix

# before
options: --security-opt seccomp

# after
options: --security-opt seccomp=unconfined
Defensive patterns

Strategy: validation

Validate before calling

for _, opt := range securityOpts {
    k, v, hasEq := strings.Cut(opt, "=")
    if !hasEq { _, v, _ = strings.Cut(opt, ":") }
    if v == "" && k != "no-new-privileges" {
        return fmt.Errorf("security-opt %q needs a value", opt)
    }
}

Prevention

When it happens

Trigger: Passing --security-opt seccomp (no value), --security-opt apparmor: (empty value), or a misspelled 'no-new-priviledges' (typo, so the exemption does not apply) in job/container options.

Common situations: Typos in the valueless option name; assuming all security opts are valueless; YAML stripping empty-string values to bare keys; copying examples that used shell-quoting that got mangled.

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/8b0f6d9c30dcfdf2. Report an issue: GitHub.