glsec

Rules / GL086

GL086 Script line that YAML parses as a mapping

Severity: error
OWASP: CICD-SEC-7 – Insecure System Configuration
CWE: CWE-710 – Improper Adherence to Coding Standards

Risk

In YAML, a plain (unquoted) scalar that contains : (colon and space) is a key–value pair. A script line such as

- curl -H "Authorization: Bearer $DEPLOY_TOKEN" https://hooks.example.com/deploy

is read as the mapping {'curl -H "Authorization': 'Bearer $DEPLOY_TOKEN" https://hooks.example.com/deploy'}, not as a command. Double quotes around an argument don't help, because the line itself starts unquoted.

GitLab accepts the file on push and rejects it only when it creates the pipeline, with script config should be a string or a nested array of strings, which doesn't point at the colon. Until then, the line is no command at all, and static checks that read script lines, glsec's own included, don't see what it would do.

What glsec checks

Every item of script:, before_script:, after_script: and hooks:pre_get_sources_script:, in jobs, under default: and at the top level, including items of nested lists. An item that is a mapping is reported at its line.

Trigger example

deploy:
  script:
    - curl -H "Authorization: Bearer $DEPLOY_TOKEN" "https://hooks.example.com/deploy"

Safe alternatives

Quote the whole line:

deploy:
  script:
    - 'curl -H "Authorization: Bearer $DEPLOY_TOKEN" "https://hooks.example.com/deploy"'

Use a block scalar:

deploy:
  script:
    - |
      curl -H "Authorization: Bearer $DEPLOY_TOKEN" "https://hooks.example.com/deploy"

Not flagged

See also

Documentation for glsec 1.24.0. Source of this page · Rule implementation