Control: 3.1.7 Ensure dependencies are pinned to a specific, verified version
Description
Pin dependencies to a specific version. Avoid using the "latest" tag or broad version.
Rationale
When using a wildcard version of a package, or the "latest" tag, the risk of encountering a new, potentially malicious package increases. The "latest" tag pulls the last package pushed to the registry. This means that if an attacker pushes a new, malicious package successfully to the registry, the next user who pulls the "latest" will pull it and risk attack. This same rule applies to a wildcard version. Assuming one is using version v1.*, it will install the latest version of the major version 1, meaning that if an attacker can push a malicious package with that same version, those using it will be subject to possible attack. By using a secure, verified version, use is restricted to this version only and no other may be pulled, decreasing the risk for any malicious package.
Audit
For every dependency in use, ensure it is pinned to a specific version.
Remediation
For every dependency in use, pin to a specific version.
Usage
Run the control in your terminal:
powerpipe control run github_compliance.control.cis_supply_chain_v100_3_1_7
Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run github_compliance.control.cis_supply_chain_v100_3_1_7 --share
SQL
This control uses a named query:
with repositories as ( select name_with_owner, url from github_my_repository order by name_with_owner),pipelines as ( select name, repository_full_name, pipeline from github_workflow where repository_full_name in (select name_with_owner from repositories)),unpinned_task_count as ( select count(*) filter (where step ->> 'type' = 'task' and (step -> 'task' ->> 'version_type')::text != 'commit' ) as unpinned_task_count, count(*) filter (where step ->> 'type' = 'task' and (step -> 'task' ->> 'version_type')::text = 'commit' ) as pinned_task_count, p.repository_full_name from pipelines as p, jsonb_array_elements(pipeline -> 'jobs') as job, jsonb_array_elements(job -> 'steps') as step group by repository_full_name)select -- Required Columns r.url as resource, case when u.unpinned_task_count > 0 then 'alarm' else 'ok' end as status, case when u.unpinned_task_count > 0 then unpinned_task_count::text || ' task(s) are not pinned.' when u.repository_full_name is null then 'No build task(s) in the repository.' else 'All task(s) are pinned.' end as reason, -- Additional Dimensions r.name_with_ownerfrom repositories as r left join unpinned_task_count as u on r.name_with_owner = u.repository_full_name;