glsec

Rules / GL030

GL030 ssh-keyscan executed dynamically in script (MITM risk)

Severity: warn
OWASP: CICD-SEC-7 – Insecure System Configuration

What glsec checks

glsec flags any script line that invokes ssh-keyscan. Running ssh-keyscan at pipeline runtime blindly trusts whatever public key the remote host presents at that moment. If the network path is compromised — shared runner network, DNS poisoning, or a rogue router — the runner will accept a fraudulent host key and the attacker can intercept the SSH session, including any secrets transmitted over it.

This pattern dominates GitLab CI SSH-deploy tutorials and is present in many real-world projects, despite GitLab's own SSH documentation explicitly warning against it.

Trigger example

before_script:
  - mkdir -p ~/.ssh
  - ssh-keyscan -H 'deploy.example.com' >> ~/.ssh/known_hosts

Safe alternative

Store a pre-verified known-hosts entry in a protected, masked CI variable and write it directly — no network call needed:

before_script:
  - mkdir -p ~/.ssh
  - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts

To obtain the entry: run ssh-keyscan <host> once from a trusted machine, verify the fingerprint out-of-band, then store the output as a CI variable named SSH_KNOWN_HOSTS.

References

See also

Enable the ShellCheck integration to surface additional shell issues in these script blocks.

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