{"id":49863742,"url":"https://github.com/glsec/glsec","last_synced_at":"2026-05-23T13:03:08.455Z","repository":{"id":357804763,"uuid":"1238611883","full_name":"glsec/glsec","owner":"glsec","description":"GitLab CI security linter — find misconfigurations and vulnerabilities in .gitlab-ci.yml files","archived":false,"fork":false,"pushed_at":"2026-05-14T21:08:03.000Z","size":1726,"stargazers_count":0,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-14T23:40:39.200Z","etag":null,"topics":["devops","devsecops","gitlab","gitlab-ci","go","linter","security"],"latest_commit_sha":null,"homepage":"https://github.com/glsec/glsec","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/glsec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T09:28:35.000Z","updated_at":"2026-05-14T21:07:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/glsec/glsec","commit_stats":null,"previous_names":["glsec/glsec"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/glsec/glsec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glsec%2Fglsec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glsec%2Fglsec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glsec%2Fglsec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glsec%2Fglsec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/glsec","download_url":"https://codeload.github.com/glsec/glsec/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glsec%2Fglsec/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33396576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["devops","devsecops","gitlab","gitlab-ci","go","linter","security"],"created_at":"2026-05-14T23:01:28.530Z","updated_at":"2026-05-23T13:03:08.449Z","avatar_url":"https://github.com/glsec.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/glsec-bg.png\" alt=\"glsec\" width=\"400\"\u003e\n\u003c/p\u003e\n\n# glsec\n\n**glsec** is a security linter for `.gitlab-ci.yml` files. It detects misconfigurations that can lead to supply-chain attacks, secret leakage, and token exfiltration — the same class of issues that [zizmor](https://github.com/zizmorcore/zizmor) and [actionlint](https://github.com/rhysd/actionlint) catch in GitHub Actions, but for GitLab CI.\n\n```\n$ glsec .gitlab-ci.yml\n\nERROR  .gitlab-ci.yml:7   GL001  image \"node:latest\" uses mutable tag \"latest\" — pin to a specific version or digest\nWARN   .gitlab-ci.yml:14  GL002  variable $CI_COMMIT_REF_NAME in script is user-controlled and unquoted — wrap in double quotes\nERROR  .gitlab-ci.yml:3   GL003  project include \"company/templates\" missing \"ref\" — defaults to HEAD of default branch (mutable)\n```\n\n## Why glsec?\n\n| Tool | Scope |\n|------|-------|\n| [zizmor](https://github.com/zizmorcore/zizmor) | GitHub Actions security |\n| [actionlint](https://github.com/rhysd/actionlint) | GitHub Actions syntax + some security |\n| [gitlab-ci-lint](https://docs.gitlab.com/api/lint/) | GitLab CI syntax only (requires API access) |\n| **glsec** | GitLab CI security — works offline, no API key needed |\n\n## Install\n\n**Go install (requires Go 1.21+):**\n\n```sh\ngo install github.com/glsec/glsec@latest\n```\n\n**Binary download:**\n\nPre-built binaries for Linux, macOS, and Windows (amd64 + arm64) are available on the [Releases page](https://github.com/glsec/glsec/releases).\n\n```sh\n# Example: Linux amd64\ncurl -sSL https://github.com/glsec/glsec/releases/latest/download/glsec_linux_amd64.tar.gz | tar xz\n./glsec --version\n```\n\nHomebrew coming soon.\n\n## Usage\n\n```sh\n# scan a file (exits 1 on error findings, 0 if clean, 2 on parse error)\nglsec .gitlab-ci.yml\n\n# JSON output for machine consumption\nglsec --format json .gitlab-ci.yml\n\n# SARIF output for GitHub Code Scanning / GitLab SAST\nglsec --format sarif .gitlab-ci.yml \u003e gl.sarif\n\n# Code Climate output for GitLab Code Quality (inline MR findings, works on all tiers)\nglsec --format codeclimate .gitlab-ci.yml \u003e gl-code-quality.json\n\n# treat warn findings as hard failures (exit 1)\nglsec --strict .gitlab-ci.yml\n\n# advisory mode: always exit 0, even with findings\nglsec --no-exit-codes .gitlab-ci.yml\n\n# exclude a file or directory from scanning\nglsec --exclude vendor/ .gitlab-ci.yml\n\n# baseline existing findings so only new violations are reported\nglsec --generate-ignore .gitlab-ci.yml\nglsec .gitlab-ci.yml  # now exits 0; new violations will be caught\n```\n\n### Exit codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | No `error`-severity findings (warn-only findings exit 0 by default) |\n| 1 | One or more `error` findings; or any finding when `--strict` is set |\n| 2 | Usage error or file could not be parsed |\n\nUse `--strict` to treat `warn` findings as hard failures (exit 1). Use `--no-exit-codes` to always exit 0 regardless of findings (advisory/informational mode). All flags can also be set in `.glsec.yml`:\n\n```yaml\nstrict: true        # warn findings cause exit 1\nno-exit-codes: true # never exit 1 (overrides strict)\n\nexclude_paths:\n  - legacy/.gitlab-ci.yml\n  - infra/old-pipelines/**\n  - vendor/\n```\n\n## Rules\n\n52 rules across 8 [OWASP CI/CD security categories](https://owasp.org/www-project-top-10-ci-cd-security-risks/):\n\n| Category | OWASP | Rules |\n|----------|-------|-------|\n| Credential Hygiene | CICD-SEC-6 | GL002, GL004, GL006, GL010, GL014, GL018, GL021, GL027, GL029, GL032, GL033, GL035, GL036, GL037, GL038, GL040, GL052 |\n| Dependency \u0026 Image Pinning | CICD-SEC-3 | GL001, GL003, GL015, GL022, GL023, GL026, GL046 |\n| Component \u0026 Third-Party Integrity | CICD-SEC-4, CICD-SEC-8 | GL041, GL044, GL051 |\n| Supply Chain Integrity | CICD-SEC-9 | GL011, GL020, GL025, GL045 |\n| Pipeline Flow \u0026 Access Control | CICD-SEC-1, CICD-SEC-5 | GL008, GL009, GL012, GL013, GL017, GL019, GL034, GL039, GL043 |\n| Insecure Configuration | CICD-SEC-7 | GL005, GL007, GL016, GL024, GL028, GL030, GL031, GL042, GL047, GL048, GL049, GL050 |\n\n→ **[Full rule reference with descriptions and examples](docs/rules.md)**\n\n**Not covered:** [CICD-SEC-2](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-02-Inadequate-Identity-And-Access-Management) (Identity \u0026 Access Management) and [CICD-SEC-10](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-10-Insufficient-Logging-And-Visibility) (Insufficient Logging \u0026 Visibility) are not detectable from static `.gitlab-ci.yml` analysis — they require platform-level context such as GitLab group/project settings, audit logs, or API access.\n\n## ShellCheck integration\n\nglsec can optionally pass `script:`, `before_script:`, and `after_script:` blocks to [ShellCheck](https://www.shellcheck.net/) for deeper shell analysis. This is **opt-in** and requires ShellCheck to be installed separately.\n\nEnable it in `.glsec.yml`:\n\n```yaml\nshellcheck:\n  enabled: true\n  path: /usr/bin/shellcheck  # optional — defaults to PATH lookup\n```\n\nShellCheck findings are reported alongside GL findings and use `SC` rule IDs:\n\n```\nWARN   .gitlab-ci.yml:12  SC2086  [build]  Double quote to prevent globbing and word splitting.\n```\n\nIf the ShellCheck binary is not found, glsec prints a warning to stderr and continues scanning normally.\n\n**Suppressing specific codes** — inline:\n\n```yaml\n  script:\n    - echo $CI_COMMIT_REF_NAME  # glsec:ignore SC2086 -- set by platform\n```\n\nOr globally in `.glsec.yml`:\n\n```yaml\nrules:\n  SC2086: off\n```\n\nShellCheck's own inline directives (`# shellcheck disable=SC2086`) are also respected.\n\n---\n\n## CI integration\n\n\u003e **Runnable examples for every pattern below:** [gitlab.com/glsec-io/examples](https://gitlab.com/glsec-io/examples) — [Catalog component](https://gitlab.com/glsec-io/examples/component) · [Catalog + Code Quality](https://gitlab.com/glsec-io/examples/component-code-quality) · [Docker image](https://gitlab.com/glsec-io/examples/docker) · [Binary download](https://gitlab.com/glsec-io/examples/binary)\n\n### GitLab CI Catalog component (recommended)\n\nUse the official component from the [GitLab CI Catalog](https://gitlab.com/explore/catalog/glsec-io/glsec) — no need to manage image pins or script wiring yourself:\n\n```yaml\ninclude:\n  - component: gitlab.com/glsec-io/glsec/glsec@v1.0.2\n\nstages:\n  - test\n```\n\nFor inline findings on merge request diffs, add the `glsec-code-quality` template — works on **all GitLab tiers**, no Ultimate required:\n\n```yaml\ninclude:\n  - component: gitlab.com/glsec-io/glsec/glsec-code-quality@v1.0.2\n\nstages:\n  - test\n```\n\nPin to an explicit component tag (not `@~latest`) — glsec's own GL003 / GL041 rules flag floating refs.\n\n**Coloured output in CI logs:** glsec auto-disables ANSI colors when stdout is not a terminal (the standard convention). Force colors back on by setting `FORCE_COLOR=1` (or `CLICOLOR_FORCE=1`) in your pipeline variables:\n\n```yaml\nvariables:\n  FORCE_COLOR: \"1\"\n```\n\n**Component repo and full input reference:** https://gitlab.com/glsec-io/glsec\n\n**Runnable example projects:** https://gitlab.com/glsec-io/examples\n\n### GitLab CI — Docker image\n\nIf you need more control than the Catalog component offers, use the pre-built image from GHCR directly:\n\n```yaml\nglsec:\n  stage: test\n  image:\n    name: ghcr.io/glsec/glsec:1.2.0\n    entrypoint: [\"\"]\n  script:\n    - glsec .gitlab-ci.yml\n```\n\nThe `entrypoint: [\"\"]` override is required: the image sets `ENTRYPOINT [\"glsec\"]` for `docker run` convenience, which conflicts with GitLab Runner's shell wrapper. Pin to a specific tag (`1.2.0`, not `:latest`) for reproducible pipelines.\n\n### GitLab CI — binary download\n\nFor pipelines that cannot pull from GHCR:\n\n```yaml\nvariables:\n  GLSEC_VERSION: \"1.2.0\"\n\nglsec:\n  stage: test\n  image: alpine:3.20\n  before_script:\n    - apk add --no-cache curl tar\n    - curl -sSLO \"https://github.com/glsec/glsec/releases/download/v${GLSEC_VERSION}/glsec_${GLSEC_VERSION}_linux_amd64.tar.gz\"\n    - curl -sSL \"https://github.com/glsec/glsec/releases/download/v${GLSEC_VERSION}/checksums.txt\" | grep \"glsec_${GLSEC_VERSION}_linux_amd64.tar.gz\" | sha256sum -c\n    - tar xzf \"glsec_${GLSEC_VERSION}_linux_amd64.tar.gz\"\n  script:\n    - ./glsec .gitlab-ci.yml\n```\n\n### GitLab SAST integration\n\nPublish findings to GitLab's Security Dashboard by emitting SARIF and exposing it as a SAST report artifact:\n\n```yaml\nglsec:\n  stage: test\n  image:\n    name: ghcr.io/glsec/glsec:1.2.0\n    entrypoint: [\"\"]\n  script:\n    - glsec --format sarif .gitlab-ci.yml \u003e glsec.sarif || true\n  artifacts:\n    reports:\n      sast: glsec.sarif\n```\n\nFindings appear in the pipeline Security tab and the project Security Dashboard. Use `|| true` to prevent the glsec job itself from blocking the pipeline — the SAST report is uploaded regardless.\n\n### GitLab Code Quality integration\n\nShow findings **inline on merge request diffs** using GitLab's Code Quality widget — works on all GitLab tiers (no Ultimate required, unlike SAST). The easiest path is the `glsec-code-quality` template from the [Catalog component](#gitlab-ci-catalog-component-recommended) above. The equivalent manual setup:\n\n```yaml\nglsec:\n  stage: test\n  image:\n    name: ghcr.io/glsec/glsec:1.2.0\n    entrypoint: [\"\"]\n  script:\n    - glsec --format codeclimate .gitlab-ci.yml \u003e gl-code-quality.json || true\n  artifacts:\n    reports:\n      codequality: gl-code-quality.json\n```\n\nSeverity mapping (glsec → Code Climate): `error` → `critical`, `warn` → `major`, `info` → `info`.\n\n### GitHub Actions\n\n```yaml\n- name: Run glsec\n  run: |\n    curl -sSLO https://github.com/glsec/glsec/releases/latest/download/glsec_linux_amd64.tar.gz\n    tar xzf glsec_linux_amd64.tar.gz\n    ./glsec .gitlab-ci.yml\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglsec%2Fglsec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglsec%2Fglsec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglsec%2Fglsec/lists"}