Merge branch 'master' into steps

This commit is contained in:
Jorge
2024-02-21 15:31:42 +01:00
committed by GitHub
51 changed files with 32564 additions and 421 deletions

1
.github/action/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

30718
.github/action/dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

175
.github/action/dist/licenses.txt vendored Normal file
View File

@@ -0,0 +1,175 @@
@actions/core
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/exec
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/http-client
MIT
Actions Http Client for Node.js
Copyright (c) GitHub, Inc.
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/io
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/tool-cache
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@fastify/busboy
MIT
Copyright Brian White. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
semver
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
tunnel
MIT
The MIT License (MIT)
Copyright (c) 2012 Koichi Kobayashi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
undici
MIT
MIT License
Copyright (c) Matteo Collina and Undici contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
uuid
MIT
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

639
.github/action/package-lock.json generated vendored Normal file
View File

@@ -0,0 +1,639 @@
{
"name": "codeql-actions-action",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "codeql-actions-action",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@actions/tool-cache": "^2.0.1"
},
"devDependencies": {
"@types/node": "^20.6.0",
"@vercel/ncc": "^0.38.0",
"prettier": "^3.0.3",
"typescript": "^5.2.2"
}
},
"node_modules/@actions/core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
}
},
"node_modules/@actions/http-client": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^5.25.4"
}
},
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@actions/tool-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz",
"integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^2.0.1",
"@actions/io": "^1.1.1",
"semver": "^6.1.0",
"uuid": "^3.3.2"
}
},
"node_modules/@actions/tool-cache/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/@fastify/busboy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
"engines": {
"node": ">=14"
}
},
"node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"dependencies": {
"@octokit/types": "^6.0.3"
}
},
"node_modules/@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"dependencies": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"dependencies": {
"@octokit/types": "^6.40.0"
},
"peerDependencies": {
"@octokit/core": ">=2"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
"dependencies": {
"@octokit/types": "^6.39.0",
"deprecation": "^2.3.1"
},
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"dependencies": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
}
},
"node_modules/@types/node": {
"version": "20.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
"integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@vercel/ncc": {
"version": "0.38.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz",
"integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==",
"dev": true,
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/prettier": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
"integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/typescript": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici": {
"version": "5.28.3",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"node_modules/universal-user-agent": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
},
"dependencies": {
"@actions/core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"requires": {
"@actions/io": "^1.0.1"
}
},
"@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"requires": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
}
},
"@actions/http-client": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
"requires": {
"tunnel": "^0.0.6",
"undici": "^5.25.4"
}
},
"@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"@actions/tool-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz",
"integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==",
"requires": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^2.0.1",
"@actions/io": "^1.1.1",
"semver": "^6.1.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"@fastify/busboy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
"integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA=="
},
"@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"requires": {
"@octokit/types": "^6.0.3"
}
},
"@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"requires": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"requires": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"requires": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"requires": {
"@octokit/types": "^6.40.0"
}
},
"@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
"requires": {
"@octokit/types": "^6.39.0",
"deprecation": "^2.3.1"
}
},
"@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"requires": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"requires": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"requires": {
"@octokit/openapi-types": "^12.11.0"
}
},
"@types/node": {
"version": "20.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
"integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
"dev": true,
"requires": {
"undici-types": "~5.26.4"
}
},
"@vercel/ncc": {
"version": "0.38.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz",
"integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==",
"dev": true
},
"before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
},
"node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
},
"prettier": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
"integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
"dev": true
},
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"typescript": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true
},
"undici": {
"version": "5.28.3",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
"requires": {
"@fastify/busboy": "^2.0.0"
}
},
"undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"universal-user-agent": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}

48
.github/action/package.json vendored Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "codeql-actions-action",
"version": "0.1.0",
"description": "CodeQL Pack to analyze GitHub Actions and Workflows",
"main": "dist/index.js",
"scripts": {
"bundle": "npm run format:write && npm run package",
"cli": "ts-node src/index.ts",
"ci-test": "jest",
"format:write": "prettier --write **/*.ts",
"format:check": "prettier --check **/*.ts",
"lint": "npx eslint . -c ./.github/linters/.eslintrc.yml",
"package": "ncc build src/index.ts --license licenses.txt",
"package:watch": "npm run package -- --watch",
"test": "(jest && make-coverage-badge --output-path ./badges/coverage.svg) || make-coverage-badge --output-path ./badges/coverage.svg",
"all": "npm run format:write && npm run lint && npm run test && npm run package"
},
"repository": {
"type": "git",
"url": "git+https://github.com/GitHubSecurityLab/codeql-actions.git"
},
"exports": {
".": "./dist/index.js"
},
"keywords": [
"codeql",
"security",
"actions"
],
"author": "Pwntester",
"license": "MIT",
"bugs": {
"url": "https://github.com/GitHubSecurityLab/codeql-actions/issues"
},
"homepage": "https://github.com/GitHubSecurityLab/codeql-actions#readme",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@actions/tool-cache": "^2.0.1"
},
"devDependencies": {
"@types/node": "^20.6.0",
"@vercel/ncc": "^0.38.0",
"prettier": "^3.0.3",
"typescript": "^5.2.2"
}
}

164
.github/action/src/codeql.ts vendored Normal file
View File

@@ -0,0 +1,164 @@
import * as fs from "fs";
import * as path from "path";
import * as core from "@actions/core";
import * as toolcache from "@actions/tool-cache";
import * as toolrunner from "@actions/exec/lib/toolrunner";
export interface CodeQLConfig {
// The path to the codeql bundle.
path: string;
// The language to use for analysis.
language: string;
// CodeQL pack to use for analysis.
pack: string;
// The codeql suite to use for analysis.
suite: string;
// The source root to use for analysis.
source_root?: string;
// The output file for the SARIF file.
output?: string;
}
export async function newCodeQL(): Promise<CodeQLConfig> {
return {
language: "yaml",
path: await findCodeQL(),
pack: "githubsecuritylab/actions-queries",
suite: "codeql-suites/actions-code-scanning.qls",
source_root: core.getInput("source-root"),
output: core.getInput("sarif"),
};
}
export async function runCommand(
config: CodeQLConfig,
args: string[],
cwd_arg?: string,
): Promise<any> {
var bin = path.join(config.path, "codeql");
let output = "";
var cwd: string = process.cwd();
if (cwd_arg) {
cwd = cwd_arg;
}
core.info("Current working directory: " + cwd);
var options = {
cwd: cwd,
listeners: {
stdout: (data: Buffer) => {
output += data.toString();
},
},
};
await new toolrunner.ToolRunner(bin, args, options).exec();
core.debug(`Finished running command :: ${bin} ${args.join(" ")}`);
return output.trim();
}
export async function runCommandJson(
config: CodeQLConfig,
args: string[],
): Promise<object> {
return JSON.parse(await runCommand(config, args));
}
async function findCodeQL(): Promise<string> {
// check if codeql is in the toolcache
var codeqlPath = await findCodeQlInToolcache();
if (codeqlPath !== undefined) {
return codeqlPath;
}
// default to the codeql in the path
return "codeql";
}
async function findCodeQlInToolcache(): Promise<string | undefined> {
const candidates = toolcache
.findAllVersions("CodeQL")
.map((version) => ({
folder: toolcache.find("CodeQL", version),
version,
}))
.filter(({ folder }) => fs.existsSync(path.join(folder, "pinned-version")));
if (candidates.length === 1) {
const candidate = candidates[0];
core.info(`CodeQL tools found in toolcache: '${candidate.folder}'.`);
core.debug(`CodeQL toolcache version: '${candidate.version}'.`);
return path.join(candidate.folder, "codeql");
}
core.warning(`No CodeQL tools found in toolcache.`);
return undefined;
}
export async function downloadPack(codeql: CodeQLConfig): Promise<boolean> {
try {
await runCommand(codeql, ["pack", "download", codeql.pack]);
return true;
} catch (error) {
core.warning("Failed to download pack from GitHub...");
}
return false;
}
export async function codeqlDatabaseCreate(
codeql: CodeQLConfig,
): Promise<string> {
// get runner temp directory for database
var temp = process.env["RUNNER_TEMP"];
if (temp === undefined) {
temp = "/tmp";
}
var database_path = path.join(temp, "codeql-actions-db");
var source_root =
codeql.source_root || process.env["GITHUB_WORKSPACE"] || "./";
await runCommand(codeql, [
"database",
"create",
"--language",
codeql.language,
"--source-root",
source_root,
database_path,
]);
return database_path;
}
export async function codeqlDatabaseAnalyze(
codeql: CodeQLConfig,
database_path: string,
): Promise<string> {
var codeql_output = codeql.output || "codeql-actions.sarif";
var cmd = [
"database",
"analyze",
"--format",
"sarif-latest",
"--sarif-add-query-help",
"--output",
codeql_output,
];
// remote pack or local pack
if (codeql.pack.startsWith("githubsecuritylab/")) {
var suite = codeql.pack + ":" + codeql.suite;
} else {
// assume path
var suite = path.join(codeql.pack, codeql.suite);
cmd.push("--search-path", codeql.pack);
}
cmd.push(database_path, suite);
await runCommand(codeql, cmd);
return codeql_output;
}

61
.github/action/src/index.ts vendored Normal file
View File

@@ -0,0 +1,61 @@
import * as path from "path";
import * as core from "@actions/core";
import * as cql from "./codeql";
/**
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
*/
export async function run(): Promise<void> {
try {
// set up codeql
var codeql = await cql.newCodeQL();
core.debug(`CodeQL CLI found at '${codeql.path}'`);
await cql.runCommand(codeql, ["version", "--format", "terse"]);
// check yaml support
var languages = await cql.runCommandJson(codeql, [
"resolve",
"languages",
"--format",
"json",
]);
if (!languages.hasOwnProperty("yaml")) {
core.setFailed("CodeQL Yaml extractor not installed");
throw new Error("CodeQL Yaml extractor not installed");
}
// download pack
core.info(`Downloading CodeQL Actions pack '${codeql.pack}'`);
var pack_downloaded = await cql.downloadPack(codeql);
if (pack_downloaded === false) {
var action_path = path.resolve(path.join(__dirname, "..", "..", ".."));
codeql.pack = path.join(action_path, "ql", "src");
core.info(`Pack defaulting back to local pack: '${codeql.pack}'`);
} else {
core.info(`Pack downloaded '${codeql.pack}'`);
}
core.info("Creating CodeQL database...");
var database_path = await cql.codeqlDatabaseCreate(codeql);
core.info("Running CodeQL analysis...");
var sarif = await cql.codeqlDatabaseAnalyze(codeql, database_path);
core.info(`SARIF results: '${sarif}'`);
core.setOutput("sarif", sarif);
core.info("Finished CodeQL analysis");
} catch (error) {
// Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message);
}
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();

24
.github/action/tsconfig.json vendored Normal file
View File

@@ -0,0 +1,24 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"rootDir": "./src",
"moduleResolution": "NodeNext",
"baseUrl": "./",
"sourceMap": true,
"outDir": "./dist",
"noImplicitAny": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"newLine": "lf"
},
"exclude": [
"./dist",
"./node_modules",
"./__tests__",
"./coverage"
]
}

28
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Build and Compile Action
on:
pull_request:
branches: ["master", "develop"]
workflow_dispatch:
permissions:
contents: read
packages: read
pull-requests: read
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
src:
- '.github/action/**'
- 'action.yml'
- name: Run action
if: steps.changes.outputs.src == 'true'
uses: ./

31
.github/workflows/copy-to-bughalla.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Copy to Bughalla
on: push
permissions:
contents: read
jobs:
copy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.BUGHALLA_TOKEN }}
fetch-depth: 0
- run: |
rm -rf .github/workflows/copy-to-bughalla.yml
git remote set-url --push origin git@github.com:bughalla/codeql-actions
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add -v .
git commit -m 'Actions: Add patch'
- name: Push changes
uses: ad-m/github-push-action@35284cf030a5836cb567a7bf1b39ebafbfae5f4a
with:
repository: bughalla/codeql-actions
github_token: ${{ secrets.BUGHALLA_TOKEN }}
branch: ${{ github.ref }}
force: true

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
.DS_Store
**/*.testproj
ql/lib/.codeql/
ql/src/.codeql/

25
action.yml Normal file
View File

@@ -0,0 +1,25 @@
name: "codeql-actions"
description: "CodeQL Pack for GitHub Actions and Workflows"
inputs:
token:
description: GitHub Token
default: ${{ github.token }}
source-root:
description: "Path of the root source code directory, relative to $GITHUB_WORKSPACE."
default: ${{ github.workspace }}
sarif-output:
description: "SARIF File Output"
default: "codeql-actions.sarif"
runs:
using: 'composite'
steps:
- name: Do something with context
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
node ${{ github.action_path }}/.github/action/dist/index.js

View File

@@ -95,6 +95,8 @@ class OutputsStmt extends Statement instanceof YamlMapping {
this.(YamlMapping).lookup(name).(YamlMapping).lookup("value") = result or
this.(YamlMapping).lookup(name) = result
}
string getAnOutputName() { this.(YamlMapping).maps(any(YamlString s | s.getValue() = result), _) }
}
class InputExpr extends Expression instanceof YamlString {
@@ -147,7 +149,7 @@ class JobStmt extends Statement instanceof Actions::Job {
* out1: ${steps.foo.bar}
* out2: ${steps.foo.baz}
*/
JobOutputStmt getOutputStmt() { result = this.(Actions::Job).lookup("outputs") }
OutputsStmt getOutputsStmt() { result = this.(Actions::Job).lookup("outputs") }
/**
* Reusable workflow jobs may have Uses children
@@ -158,27 +160,9 @@ class JobStmt extends Statement instanceof Actions::Job {
* arg1: value1
*/
JobUsesExpr getUsesExpr() { result.getJobStmt() = this }
}
/**
* Declaration of the outputs for the job.
* eg:
* out1: ${steps.foo.bar}
* out2: ${steps.foo.baz}
*/
class JobOutputStmt extends Statement instanceof YamlMapping {
JobStmt job;
JobOutputStmt() { job.(YamlMapping).lookup("outputs") = this }
YamlMapping asYamlMapping() { result = this }
/**
* Gets a specific value expression
* eg: ${steps.foo.bar}
*/
Expression getOutputExpr(string id) {
this.(YamlMapping).maps(any(YamlScalar s | s.getValue() = id), result)
predicate usesReusableWorkflow() {
this.(YamlMapping).maps(any(YamlString s | s.getValue() = "uses"), _)
}
}
@@ -353,26 +337,60 @@ class ExprAccessExpr extends Expression instanceof YamlString {
string getExpression() { result = expr }
JobStmt getJobStmt() { result.getAChildNode*() = this }
}
/**
* A context access expression.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
*/
class CtxAccessExpr extends ExprAccessExpr {
CtxAccessExpr() {
expr.regexpMatch([
stepsCtxRegex(), needsCtxRegex(), jobsCtxRegex(), envCtxRegex(), inputsCtxRegex()
])
}
abstract string getFieldName();
abstract Expression getRefExpr();
}
private string stepsCtxRegex() {
result = "\\bsteps\\.([A-Za-z0-9_-]+)\\.outputs\\.([A-Za-z0-9_-]+)\\b"
}
private string needsCtxRegex() {
result = "\\bneeds\\.([A-Za-z0-9_-]+)\\.outputs\\.([A-Za-z0-9_-]+)\\b"
}
private string jobsCtxRegex() {
result = "\\bjobs\\.([A-Za-z0-9_-]+)\\.outputs\\.([A-Za-z0-9_-]+)\\b"
}
private string envCtxRegex() { result = "\\benv\\.([A-Za-z0-9_-]+)\\b" }
private string inputsCtxRegex() {
result = "\\binputs\\.([A-Za-z0-9_-]+)\\b" or
result = "\\bgithub\\.event\\.inputs\\.([A-Za-z0-9_-]+)\\b"
}
/**
* Holds for an ExprAccessExpr accesing the `steps` context.
* Holds for an expression accesing the `steps` context.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ steps.changed-files.outputs.all_changed_files }}`
*/
class StepOutputAccessExpr extends ExprAccessExpr {
class StepsCtxAccessExpr extends CtxAccessExpr {
string stepId;
string varName;
string fieldName;
StepOutputAccessExpr() {
stepId =
this.getExpression().regexpCapture("steps\\.([A-Za-z0-9_-]+)\\.outputs\\.[A-Za-z0-9_-]+", 1) and
varName =
this.getExpression().regexpCapture("steps\\.[A-Za-z0-9_-]+\\.outputs\\.([A-Za-z0-9_-]+)", 1)
StepsCtxAccessExpr() {
expr.regexpMatch(stepsCtxRegex()) and
stepId = expr.regexpCapture(stepsCtxRegex(), 1) and
fieldName = expr.regexpCapture(stepsCtxRegex(), 2)
}
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
this.getLocation().getFile() = result.getLocation().getFile() and
result.(StepStmt).getId() = stepId
@@ -380,79 +398,112 @@ class StepOutputAccessExpr extends ExprAccessExpr {
}
/**
* Holds for an ExprAccessExpr accesing the `needs` or `job` contexts.
* Holds for an expression accesing the `needs` context.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ needs.job1.outputs.foo}}` or `${{ jobs.job1.outputs.foo}}` (for reusable workflows)
* e.g. `${{ needs.job1.outputs.foo}}`
*/
class JobOutputAccessExpr extends ExprAccessExpr {
class NeedsCtxAccessExpr extends CtxAccessExpr {
JobStmt job;
string jobId;
string varName;
string fieldName;
JobOutputAccessExpr() {
jobId =
this.getExpression()
.regexpCapture("(needs|jobs)\\.([A-Za-z0-9_-]+)\\.outputs\\.[A-Za-z0-9_-]+", 2) and
varName =
this.getExpression()
.regexpCapture("(needs|jobs)\\.[A-Za-z0-9_-]+\\.outputs\\.([A-Za-z0-9_-]+)", 2)
NeedsCtxAccessExpr() {
expr.regexpMatch(needsCtxRegex()) and
jobId = expr.regexpCapture(needsCtxRegex(), 1) and
fieldName = expr.regexpCapture(needsCtxRegex(), 2) and
job.getId() = jobId
}
predicate usesReusableWorkflow() { job.usesReusableWorkflow() }
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
job.getLocation().getFile() = this.getLocation().getFile() and
(
// regular jobs
job.getOutputsStmt() = result
or
// reusable workflow calling jobs
job.getUsesExpr() = result
)
}
}
/**
* Holds for an expression accesing the `jobs` context.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ jobs.job1.outputs.foo}}` (within reusable workflows)
*/
class JobsCtxAccessExpr extends CtxAccessExpr {
string jobId;
string fieldName;
JobsCtxAccessExpr() {
expr.regexpMatch(jobsCtxRegex()) and
jobId = expr.regexpCapture(jobsCtxRegex(), 1) and
fieldName = expr.regexpCapture(jobsCtxRegex(), 2)
}
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
exists(JobStmt job |
job.getId() = jobId and
job.getLocation().getFile() = this.getLocation().getFile() and
(
// A Job can have multiple outputs, so we need to check both
// jobs.<job_id>.outputs.<output_name>
job.getOutputStmt().getOutputExpr(varName) = result
or
// jobs.<job_id>.uses (variables returned from the reusable workflow
job.getUsesExpr() = result
)
job.getOutputsStmt() = result
)
}
}
/**
* Holds for an ExprAccessExpr accesing the `inputs` context.
* Holds for an expression the `inputs` context.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ inputs.foo }}`
*/
class InputAccessExpr extends ExprAccessExpr {
string paramName;
class InputsCtxAccessExpr extends CtxAccessExpr {
string fieldName;
InputAccessExpr() {
paramName = this.getExpression().regexpCapture("inputs\\.([A-Za-z0-9_-]+)", 1)
InputsCtxAccessExpr() {
expr.regexpMatch(inputsCtxRegex()) and
fieldName = expr.regexpCapture(inputsCtxRegex(), 1)
}
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
exists(ReusableWorkflowStmt w |
w.getLocation().getFile() = this.getLocation().getFile() and
w.getInputsStmt().getInputExpr(paramName) = result
w.getInputsStmt().getInputExpr(fieldName) = result
)
or
exists(CompositeActionStmt a |
a.getLocation().getFile() = this.getLocation().getFile() and
a.getInputsStmt().getInputExpr(paramName) = result
a.getInputsStmt().getInputExpr(fieldName) = result
)
}
}
/**
* Holds for an ExprAccessExpr accesing the `env` context.
* Holds for an expression accesing the `env` context.
* https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
* e.g. `${{ env.foo }}`
*/
class EnvAccessExpr extends ExprAccessExpr {
string varName;
class EnvCtxAccessExpr extends CtxAccessExpr {
string fieldName;
EnvAccessExpr() { varName = this.getExpression().regexpCapture("env\\.([A-Za-z0-9_-]+)", 1) }
EnvCtxAccessExpr() {
expr.regexpMatch(envCtxRegex()) and
fieldName = expr.regexpCapture(envCtxRegex(), 1)
}
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
exists(JobUsesExpr s | s.getEnvExpr(varName) = result)
exists(JobUsesExpr s | s.getEnvExpr(fieldName) = result)
or
exists(StepUsesExpr s | s.getEnvExpr(varName) = result)
exists(StepUsesExpr s | s.getEnvExpr(fieldName) = result)
or
exists(RunExpr s | s.getEnvExpr(varName) = result)
exists(RunExpr s | s.getEnvExpr(fieldName) = result)
}
}

View File

@@ -7,12 +7,13 @@ module DataFlow {
private import codeql.actions.dataflow.internal.DataFlowImplSpecific
import DataFlowMake<ActionsDataFlow>
import codeql.actions.dataflow.internal.DataFlowPublic
/** debug */
// debug
private import codeql.actions.dataflow.internal.TaintTrackingImplSpecific
import codeql.dataflow.internal.DataFlowImplConsistency as DFIC
module ActionsConsistency implements DFIC::InputSig<ActionsDataFlow> { }
module Consistency {
import DFIC::MakeConsistency<ActionsDataFlow, ActionsTaintTracking, ActionsConsistency>
}
import DFIC::MakeConsistency<ActionsDataFlow, ActionsTaintTracking, ActionsConsistency>
}
}

View File

@@ -294,8 +294,10 @@ module Actions {
/** Gets the owner and name of the repository where the Action comes from, e.g. `actions/checkout` in `actions/checkout@v2`. */
string getGitHubRepository() {
result =
this.getValue().regexpCapture(usesParser(), 1) + "/" +
this.getValue().regexpCapture(usesParser(), 2)
(
this.getValue().regexpCapture(usesParser(), 1) + "/" +
this.getValue().regexpCapture(usesParser(), 2)
).toLowerCase()
}
/** Gets the version reference used when checking out the Action, e.g. `v2` in `actions/checkout@v2`. */

View File

@@ -231,7 +231,7 @@ private class JobTree extends StandardPreOrderTree instanceof JobStmt {
rank[i](Expression child, Location l |
(
child = super.getAStepStmt() or
child = super.getOutputStmt() or
child = super.getOutputsStmt() or
child = super.getUsesExpr()
) and
l = child.getLocation()
@@ -243,25 +243,9 @@ private class JobTree extends StandardPreOrderTree instanceof JobStmt {
}
}
private class JobOutputTree extends StandardPreOrderTree instanceof JobOutputStmt {
override ControlFlowTree getChildNode(int i) { result = super.asYamlMapping().getValueNode(i) }
}
private class UsesExprTree extends LeafTree instanceof UsesExpr { }
private class StepUsesTree extends StandardPreOrderTree instanceof StepUsesExpr {
override ControlFlowTree getChildNode(int i) {
result =
rank[i](Expression child, Location l |
(child = super.getArgumentExpr(_) or child = super.getEnvExpr(_)) and
l = child.getLocation()
|
child
order by
l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine(), child.toString()
)
}
}
private class JobUsesTree extends StandardPreOrderTree instanceof JobUsesExpr {
private class UsesTree extends StandardPreOrderTree instanceof UsesExpr {
override ControlFlowTree getChildNode(int i) {
result =
rank[i](Expression child, Location l |

View File

@@ -2,21 +2,31 @@ private import internal.ExternalFlowExtensions as Extensions
import codeql.actions.DataFlow
import actions
/** Holds if a source model exists for the given parameters. */
/**
* MaD sources
* Fields:
* - action: Fully-qualified action name (NWO)
* - version: Either '*' or a specific SHA/Tag
* - output arg: To node (prefixed with either `env.` or `output.`)
* - trigger: Triggering event under which this model introduces tainted data. Use `*` for any event.
*/
predicate sourceModel(string action, string version, string output, string trigger, string kind) {
Extensions::sourceModel(action, version, output, trigger, kind)
}
/** Holds if a sink model exists for the given parameters. */
/**
* MaD summaries
* Fields:
* - action: Fully-qualified action name (NWO)
* - version: Either '*' or a specific SHA/Tag
* - input arg: From node (prefixed with either `env.` or `input.`)
* - output arg: To node (prefixed with either `env.` or `output.`)
* - kind: Either 'Taint' or 'Value'
*/
predicate summaryModel(string action, string version, string input, string output, string kind) {
Extensions::summaryModel(action, version, input, output, kind)
}
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(string action, string version, string input, string kind) {
Extensions::sinkModel(action, version, input, kind)
}
/**
* MaD sinks
* Fields:
@@ -25,15 +35,67 @@ predicate sinkModel(string action, string version, string input, string kind) {
* - input: sink node (prefixed with either `env.` or `input.`)
* - kind: sink kind
*/
predicate sinkNode(DataFlow::ExprNode sink, string kind) {
predicate sinkModel(string action, string version, string input, string kind) {
Extensions::sinkModel(action, version, input, kind)
}
predicate externallyDefinedSource(DataFlow::Node source, string sourceType, string fieldName) {
exists(UsesExpr uses, string action, string version, string trigger, string kind |
sourceModel(action, version, fieldName, trigger, kind) and
uses.getCallee() = action.toLowerCase() and
(
if version.trim() = "*"
then uses.getVersion() = any(string v)
else uses.getVersion() = version.trim()
) and
(
if fieldName.trim().matches("env.%")
then source.asExpr() = uses.getEnvExpr(fieldName.trim().replaceAll("env.", ""))
else
if fieldName.trim().matches("output.%")
then source.asExpr() = uses
else none()
) and
sourceType = kind
)
}
predicate externallyDefinedStoreStep(
DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c
) {
exists(UsesExpr uses, string action, string version, string input, string output |
summaryModel(action, version, input, output, "taint") and
c = any(DataFlow::FieldContent ct | ct.getName() = output.replaceAll("output.", "")) and
uses.getCallee() = action.toLowerCase() and
(
if version.trim() = "*"
then uses.getVersion() = any(string v)
else uses.getVersion() = version.trim()
) and
(
if input.trim().matches("env.%")
then pred.asExpr() = uses.getEnvExpr(input.trim().replaceAll("env.", ""))
else
if input.trim().matches("input.%")
then pred.asExpr() = uses.getArgumentExpr(input.trim().replaceAll("input.", ""))
else none()
) and
succ.asExpr() = uses
)
}
predicate externallyDefinedSink(DataFlow::ExprNode sink, string kind) {
exists(UsesExpr uses, string action, string version, string input |
(
if input.trim().matches("env.%")
then sink.asExpr() = uses.getEnvExpr(input.trim().replaceAll("input\\.", ""))
else sink.asExpr() = uses.getArgumentExpr(input.trim())
then sink.asExpr() = uses.getEnvExpr(input.trim().replaceAll("env.", ""))
else
if input.trim().matches("input.%")
then sink.asExpr() = uses.getArgumentExpr(input.trim().replaceAll("input.", ""))
else none()
) and
sinkModel(action, version, input, kind) and
uses.getCallee() = action and
uses.getCallee() = action.toLowerCase() and
(
if version.trim() = "*"
then uses.getVersion() = any(string v)

View File

@@ -126,44 +126,18 @@ private class EventSource extends RemoteFlowSource {
}
/**
* MaD sources
* Fields:
* - action: Fully-qualified action name (NWO)
* - version: Either '*' or a specific SHA/Tag
* - output arg: To node (prefixed with either `env.` or `output.`)
* - trigger: Triggering event under which this model introduces tainted data. Use `*` for any event.
* A Source of untrusted data defined in a MaD specification
*/
private class ExternallyDefinedSource extends RemoteFlowSource {
string soutceType;
string sourceType;
ExternallyDefinedSource() {
exists(
UsesExpr uses, string action, string version, string output, string trigger, string kind
|
sourceModel(action, version, output, trigger, kind) and
uses.getCallee() = action and
(
if version.trim() = "*"
then uses.getVersion() = any(string v)
else uses.getVersion() = version.trim()
) and
(
if output.trim().matches("env.%")
then this.asExpr() = uses.getEnvExpr(output.trim().replaceAll("output\\.", ""))
else
// 'output.' is the default qualifier
// TODO: Taint just the specified output
this.asExpr() = uses
) and
soutceType = kind
)
}
ExternallyDefinedSource() { externallyDefinedSource(this, sourceType, _) }
override string getSourceType() { result = soutceType }
override string getSourceType() { result = sourceType }
}
/**
* Composite action input sources
* An input for a Composite Action
*/
private class CompositeActionInputSource extends RemoteFlowSource {
CompositeActionStmt c;

View File

@@ -21,42 +21,6 @@ class AdditionalTaintStep extends Unit {
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
}
/**
* MaD summaries
* Fields:
* - action: Fully-qualified action name (NWO)
* - version: Either '*' or a specific SHA/Tag
* - input arg: From node (prefixed with either `env.` or `input.`)
* - output arg: To node (prefixed with either `env.` or `output.`)
* - kind: Either 'Taint' or 'Value'
*/
predicate externallyDefinedSummary(DataFlow::Node pred, DataFlow::Node succ) {
exists(UsesExpr uses, string action, string version, string input |
// `output` not used yet
summaryModel(action, version, input, _, "taint") and
uses.getCallee() = action and
(
if version.trim() = "*"
then uses.getVersion() = any(string v)
else uses.getVersion() = version.trim()
) and
(
if input.trim().matches("env.%")
then pred.asExpr() = uses.getEnvExpr(input.trim().replaceAll("env\\.", ""))
else
// 'input.' is the default qualifier
pred.asExpr() = uses.getArgumentExpr(input.trim().replaceAll("input\\.", ""))
) and
succ.asExpr() = uses
)
}
private class ExternallyDefinedSummary extends AdditionalTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
externallyDefinedSummary(pred, succ)
}
}
/**
* Holds if a Run step declares an environment variable, uses it in its script and sets an output in its script.
* e.g.
@@ -65,27 +29,22 @@ private class ExternallyDefinedSummary extends AdditionalTaintStep {
* env:
* BODY: ${{ github.event.comment.body }}
* run: |
* INITIAL_URL=$(echo "$BODY" | grep -o 'https://github.com/github/release-assets/assets/[^ >]*')
* echo "Cleaned Initial URL: $INITIAL_URL"
* echo "::set-output name=initial_url::$INITIAL_URL"
* echo "::set-output name=foo::$BODY"
* echo "foo=$(echo $BODY)" >> $GITHUB_OUTPUT
* echo "foo=$(echo $BODY)" >> "$GITHUB_OUTPUT"
*/
private class RunEnvToScriptStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
runEnvToScriptstep(pred, succ)
}
}
predicate runEnvToScriptstep(DataFlow::Node pred, DataFlow::Node succ) {
exists(RunExpr r, string varName |
predicate runEnvToScriptStoreStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::ContentSet c) {
exists(RunExpr r, string varName, string output |
c = any(DataFlow::FieldContent ct | ct.getName() = output.replaceAll("output\\.", "")) and
r.getEnvExpr(varName) = pred.asExpr() and
exists(string script, string line |
script = r.getScript() and
line = script.splitAt("\n") and
(
line.regexpMatch(".*::set-output\\s+name.*") or
line.regexpMatch(".*>>\\s*\\$GITHUB_OUTPUT.*")
output = line.regexpCapture(".*::set-output\\s+name=(.*)::.*", 1) or
output = line.regexpCapture(".*echo\\s*\"(.*)=.*\\s*>>\\s*(\")?\\$GITHUB_OUTPUT.*", 1)
) and
script.indexOf("$" + ["", "{", "ENV{"] + varName) > 0
line.indexOf("$" + ["", "{", "ENV{"] + varName) > 0
) and
succ.asExpr() = r
)

View File

@@ -4,6 +4,8 @@ private import codeql.actions.Cfg as Cfg
private import codeql.Locations
private import codeql.actions.controlflow.BasicBlocks
private import DataFlowPublic
private import codeql.actions.dataflow.ExternalFlow
private import codeql.actions.dataflow.FlowSteps
cached
newtype TNode = TExprNode(DataFlowExpr e)
@@ -56,7 +58,7 @@ class DataFlowExpr extends Cfg::Node {
}
/**
* A call corresponds to a Uses steps where a 3rd party action or a reusable workflow gets called
* A call corresponds to a Uses steps where a 3rd party action or a reusable workflow get called
*/
class DataFlowCall instanceof Cfg::Node {
DataFlowCall() { super.getAstNode() instanceof UsesExpr }
@@ -129,25 +131,19 @@ predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { t1 = t2 }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
private newtype TContent = TNoContent() { none() }
newtype TContent =
TFieldContent(string name) {
// We only use field flow for steps and jobs outputs, not for accessing other context fields such as env or inputs
name = any(StepsCtxAccessExpr a).getFieldName() or
name = any(NeedsCtxAccessExpr a).getFieldName() or
name = any(JobsCtxAccessExpr a).getFieldName()
}
class Content extends TContent {
/** Gets a textual representation of this element. */
string toString() { none() }
}
predicate forceHighPrecision(Content c) { c instanceof FieldContent }
predicate forceHighPrecision(Content c) { none() }
class ContentApprox = ContentSet;
newtype TContentSet = TNoContentSet() { none() }
private newtype TContentApprox = TNoContentApprox() { none() }
class ContentApprox extends TContentApprox {
/** Gets a textual representation of this element. */
string toString() { none() }
}
ContentApprox getContentApprox(Content c) { none() }
ContentApprox getContentApprox(Content c) { result = c }
/**
* Made a string to match the ArgumentPosition type.
@@ -168,12 +164,16 @@ class ArgumentPosition extends string {
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
/**
* Holds if there is a local flow step between a ${{}} expression accesing a step output variable and the step output itself
* e.g. ${{ steps.step1.output.foo }}
* Holds if there is a local flow step between a ${{ steps.xxx.outputs.yyy }} expression accesing a step output field
* and the step output itself. But only for those cases where the step output is defined externally in a MaD Source
* specification. The reason for this is that we don't currently have a way to specify that a source starts with a
* non-empty access path so we cannot write a Source that stores the taint in a Content, we can only do that for steps
* (storeStep). The easiest thing is to add this local flow step that simulates a read step from the source node for a specific
* field name.
*/
predicate stepsCtxLocalStep(Node nodeFrom, Node nodeTo) {
exists(StepStmt astFrom, StepOutputAccessExpr astTo |
(astFrom instanceof UsesExpr or astFrom instanceof RunExpr) and
exists(UsesExpr astFrom, StepsCtxAccessExpr astTo |
externallyDefinedSource(nodeFrom, _, "output." + astTo.getFieldName()) and
astFrom = nodeFrom.asExpr() and
astTo = nodeTo.asExpr() and
astTo.getRefExpr() = astFrom
@@ -181,11 +181,16 @@ predicate stepsCtxLocalStep(Node nodeFrom, Node nodeTo) {
}
/**
* Holds if there is a local flow step between a ${{}} expression accesing a job output variable and the job output itself
* e.g. ${{ needs.job1.output.foo }} or ${{ job.job1.output.foo }}
* Holds if there is a local flow step between a ${{ needs.xxx.outputs.yyy }} expression accesing a job output field
* and the step output itself. But only for those cases where the job (needs) output is defined externally in a MaD Source
* specification. The reason for this is that we don't currently have a way to specify that a source starts with a
* non-empty access path so we cannot write a Source that stores the taint in a Content, we can only do that for steps
* (storeStep). The easiest thing is to add this local flow step that simulates a read step from the source node for a specific
* field name.
*/
predicate jobsCtxLocalStep(Node nodeFrom, Node nodeTo) {
exists(Expression astFrom, JobOutputAccessExpr astTo |
predicate needsCtxLocalStep(Node nodeFrom, Node nodeTo) {
exists(UsesExpr astFrom, NeedsCtxAccessExpr astTo |
externallyDefinedSource(nodeFrom, _, "output." + astTo.getFieldName()) and
astFrom = nodeFrom.asExpr() and
astTo = nodeTo.asExpr() and
astTo.getRefExpr() = astFrom
@@ -197,7 +202,7 @@ predicate jobsCtxLocalStep(Node nodeFrom, Node nodeTo) {
* e.g. ${{ inputs.foo }}
*/
predicate inputsCtxLocalStep(Node nodeFrom, Node nodeTo) {
exists(Expression astFrom, InputAccessExpr astTo |
exists(Expression astFrom, InputsCtxAccessExpr astTo |
astFrom = nodeFrom.asExpr() and
astTo = nodeTo.asExpr() and
astTo.getRefExpr() = astFrom
@@ -209,10 +214,13 @@ predicate inputsCtxLocalStep(Node nodeFrom, Node nodeTo) {
* e.g. ${{ env.foo }}
*/
predicate envCtxLocalStep(Node nodeFrom, Node nodeTo) {
exists(Expression astFrom, EnvAccessExpr astTo |
exists(Expression astFrom, EnvCtxAccessExpr astTo |
astFrom = nodeFrom.asExpr() and
astTo = nodeTo.asExpr() and
astTo.getRefExpr() = astFrom
(
externallyDefinedSource(nodeFrom, _, "env." + astTo.getFieldName()) or
astTo.getRefExpr() = astFrom
)
)
}
@@ -224,7 +232,7 @@ predicate envCtxLocalStep(Node nodeFrom, Node nodeTo) {
pragma[nomagic]
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
stepsCtxLocalStep(nodeFrom, nodeTo) or
jobsCtxLocalStep(nodeFrom, nodeTo) or
needsCtxLocalStep(nodeFrom, nodeTo) or
inputsCtxLocalStep(nodeFrom, nodeTo) or
envCtxLocalStep(nodeFrom, nodeTo)
}
@@ -244,19 +252,53 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { localFlowStep(nodeFr
*/
predicate jumpStep(Node nodeFrom, Node nodeTo) { none() }
/**
* Holds if a CtxAccessExpr reads a field from a job (needs/jobs), step (steps) output via a read of `c` (fieldname)
*/
predicate ctxFieldReadStep(Node node1, Node node2, ContentSet c) {
exists(CtxAccessExpr access |
(
access instanceof NeedsCtxAccessExpr or
access instanceof StepsCtxAccessExpr or
access instanceof JobsCtxAccessExpr
) and
c = any(FieldContent ct | ct.getName() = access.getFieldName()) and
node1.asExpr() = access.getRefExpr() and
node2.asExpr() = access
)
}
/**
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
* `node1` references an object with a content `c.getAReadContent()` whose
* value ends up in `node2`.
* Store steps without corresponding reads are pruned aggressively very early, since they can never contribute to a complete path.
*/
predicate readStep(Node node1, ContentSet c, Node node2) { none() }
predicate readStep(Node node1, ContentSet c, Node node2) { ctxFieldReadStep(node1, node2, c) }
/**
* Stores an output expression (node1) into its OutputsStm node (node2)
* using the output variable name as the access path
*/
predicate fieldStoreStep(Node node1, Node node2, ContentSet c) {
exists(OutputsStmt out, string fieldName |
node1.asExpr() = out.getOutputExpr(fieldName) and
node2.asExpr() = out and
c = any(FieldContent ct | ct.getName() = fieldName)
)
}
/**
* Holds if data can flow from `node1` to `node2` via a store into `c`. Thus,
* `node2` references an object with a content `c.getAStoreContent()` that
* contains the value of `node1`.
* Store steps without corresponding reads are pruned aggressively very early, since they can never contribute to a complete path.
*/
predicate storeStep(Node node1, ContentSet c, Node node2) { none() }
predicate storeStep(Node node1, ContentSet c, Node node2) {
fieldStoreStep(node1, node2, c) or
externallyDefinedStoreStep(node1, node2, c) or
runEnvToScriptStoreStep(node1, node2, c)
}
/**
* Holds if values stored inside content `c` are cleared at node `n`. For example,

View File

@@ -66,6 +66,17 @@ class ParameterNode extends ExprNode {
InputExpr getInputExpr() { result = input }
}
/**
* A call to a data flow callable (Uses).
*/
class CallNode extends ExprNode {
private DataFlowCall call;
CallNode() { this.getCfgNode() instanceof DataFlowCall }
string getCallee() { result = this.getCfgNode().(DataFlowCall).getName() }
}
/**
* An argument to a Uses step (call).
*/
@@ -83,18 +94,18 @@ class ArgumentNode extends ExprNode {
* Reusable workflow output nodes
*/
class ReturnNode extends ExprNode {
private OutputExpr output;
private OutputsStmt outputs;
ReturnNode() {
this.asExpr() = output and
output = any(OutputsStmt s).getOutputExpr(_)
this.asExpr() = outputs and
outputs = any(ReusableWorkflowStmt s).getOutputsStmt()
}
ReturnKind getKind() { result = TNormalReturn() }
override string toString() { result = "output " + output.toString() }
override string toString() { result = "output " + outputs.toString() }
override Location getLocation() { result = output.getLocation() }
override Location getLocation() { result = outputs.getLocation() }
}
/** Gets the node corresponding to `e`. */
@@ -106,13 +117,63 @@ Node exprNode(DataFlowExpr e) { result = TExprNode(e) }
* The set may be interpreted differently depending on whether it is
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
*/
class ContentSet extends TContentSet {
/** Gets a textual representation of this element. */
string toString() { none() }
class ContentSet instanceof Content {
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() { none() }
Content getAStoreContent() { result = this }
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent() { none() }
Content getAReadContent() { result = this }
/** Gets a textual representation of this content set. */
string toString() { result = super.toString() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
/**
* A reference contained in an object. Examples include instance fields, the
* contents of a collection object, the contents of an array or pointer.
*/
class Content extends TContent {
/** Gets the type of the contained data for the purpose of type pruning. */
DataFlowType getType() { any() }
/** Gets a textual representation of this element. */
abstract string toString();
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0
}
}
/** A field of an object, for example an instance variable. */
class FieldContent extends Content, TFieldContent {
private string name;
FieldContent() { this = TFieldContent(name) }
/** Gets the name of the field. */
string getName() { result = name }
override string toString() { result = name }
}

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: githubsecuritylab/actions-all
extensible: sinkModel
data:
- ["","","",""]

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: githubsecuritylab/actions-all
extensible: summaryModel
data:
- ["octo-org/this-repo/.github/workflows/workflow.yml", "*", "input.config-path", "output.workflow-output", "taint"]
- ["octo-org/summary-repo/.github/workflows/workflow.yml", "*", "input.config-path", "output.workflow-output", "taint"]
- addsTo:
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["octo-org/source-repo/.github/workflows/workflow.yml", "*", "output.workflow-output", "*", "Foo"]
- addsTo:
pack: githubsecuritylab/actions-all
extensible: sinkModel
data:
- ["octo-org/sink-repo/.github/workflows/workflow.yml", "*", "input.config-path", "expression-injection"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["ahmadnassri/action-changed-files", "*", "output.files", "pull_request", "PR changed files"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["dorny/paths-filter", "*", "output.changes", "pull_request", "PR changed files"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: summaryModel
data:
- ["frabert/replace-string-action", "*", "input.string", "output.replaced", "taint"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["jitterbit/get-changed-files", "*", "output.all", "pull_request", "PR changed files"]
@@ -16,4 +16,4 @@ extensions:
- ["jitterbit/get-changed-files", "*", "output.added_modified", "pull_request", "PR changed files"]
- ["jitterbit/get-changed-files", "*", "output.added_modified", "pull_request_target", "PR changed files"]
- ["jitterbit/get-changed-files", "*", "output.deleted", "pull_request", "PR changed files"]
- ["jitterbit/get-changed-files", "*", "output.deleted", "pull_request_target", "PR changed files"]
- ["jitterbit/get-changed-files", "*", "output.deleted", "pull_request_target", "PR changed files"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: summaryModel
data:
- ["mad9000/actions-find-and-replace-string", "*", "input.source", "output.value", "taint"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["tj-actions/changed-files", "*", "output.added_files", "pull_request", "PR changed files"]
@@ -36,4 +36,4 @@ extensions:
- ["tj-actions/changed-files", "*", "output.modified_keys", "pull_request", "PR changed files"]
- ["tj-actions/changed-files", "*", "output.modified_keys", "pull_request_target", "PR changed files"]
- ["tj-actions/changed-files", "*", "output.changed_keys", "pull_request", "PR changed files"]
- ["tj-actions/changed-files", "*", "output.changed_keys", "pull_request_target", "PR changed files"]
- ["tj-actions/changed-files", "*", "output.changed_keys", "pull_request_target", "PR changed files"]

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/actions-all
pack: githubsecuritylab/actions-all
extensible: sourceModel
data:
- ["tj-actions/verify-changed-files", "*", "output.changed-files", "pull_request", "PR changed files"]

View File

@@ -1,8 +1,8 @@
---
library: true
warnOnImplicitThis: true
name: codeql/actions-all
version: 0.0.1-dev
name: githubsecuritylab/actions-all
version: 0.0.1
dependencies:
codeql/controlflow: ^0.1.7
codeql/yaml: "*"

View File

@@ -43,14 +43,9 @@ query predicate nonOrphanVarAccesses(ExprAccessExpr va, string var, AstNode pare
query predicate parentNodes(AstNode child, AstNode parent) { child.getParentNode() = parent }
query predicate cfgNodes(Cfg::Node n) {
//any()
n.getAstNode() instanceof OutputsStmt
}
query predicate cfgNodes(Cfg::Node n) { any() }
query predicate dfNodes(DataFlow::Node e) {
e.getLocation().getFile().getBaseName() = "argus_case_study.yml"
}
query predicate dfNodes(DataFlow::Node e) { any() }
query predicate exprNodes(DataFlow::ExprNode e) { any() }
@@ -69,3 +64,7 @@ query predicate sources(string action, string version, string output, string tri
query predicate summaries(string action, string version, string input, string output, string kind) {
summaryModel(action, version, input, output, kind)
}
query predicate calls(DataFlow::CallNode call, string callee) { callee = call.getCallee() }
query predicate needs(DataFlow::ExprNode e) { e.asExpr() instanceof NeedsCtxAccessExpr }

View File

@@ -7,6 +7,7 @@
* @precision high
* @id actions/composite-action-summaries
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
@@ -17,12 +18,10 @@ import codeql.actions.dataflow.ExternalFlow
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof DataFlow::ParameterNode and
exists(CompositeActionStmt c | c.getInputsStmt().getInputExpr(_) = source.asExpr())
}
predicate isSink(DataFlow::Node sink) {
sink instanceof DataFlow::ReturnNode and
exists(CompositeActionStmt c | c.getOutputsStmt().getOutputExpr(_) = sink.asExpr())
}
}
@@ -32,5 +31,7 @@ module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Summary"

View File

@@ -0,0 +1,42 @@
/**
* @name Composite Action Sinks
* @description Actions passing input variables to expression injection sinks.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id actions/composite-action-sinks
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
import actions
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow
private class ExpressionInjectionSink extends DataFlow::Node {
ExpressionInjectionSink() {
exists(RunExpr e | e.getScriptExpr() = this.asExpr()) or
externallyDefinedSink(this, "expression-injection")
}
}
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(CompositeActionStmt c | c.getInputsStmt().getInputExpr(_) = source.asExpr())
}
predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionInjectionSink }
}
module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Sink"

View File

@@ -7,6 +7,7 @@
* @precision high
* @id actions/composite-action-sources
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
@@ -23,9 +24,15 @@ private module MyConfig implements DataFlow::ConfigSig {
}
predicate isSink(DataFlow::Node sink) {
sink instanceof DataFlow::ReturnNode and
exists(CompositeActionStmt c | c.getOutputsStmt().getOutputExpr(_) = sink.asExpr())
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
allowImplicitRead(node, set)
or
isSink(node) and
set instanceof DataFlow::FieldContent
}
}
module MyFlow = TaintTracking::Global<MyConfig>;
@@ -33,5 +40,7 @@ module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Source"

View File

@@ -0,0 +1,42 @@
/**
* @name Reusable Workflow Sinks
* @description Reusable Workflows passing parameters to an expression injection sink.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id actions/reusable-wokflow-sinks
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
import actions
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow
private class ExpressionInjectionSink extends DataFlow::Node {
ExpressionInjectionSink() {
exists(RunExpr e | e.getScriptExpr() = this.asExpr()) or
externallyDefinedSink(this, "expression-injection")
}
}
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(ReusableWorkflowStmt w | w.getInputsStmt().getInputExpr(_) = source.asExpr())
}
predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionInjectionSink }
}
module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Sink"

View File

@@ -0,0 +1,46 @@
/**
* @name Reusable Workflow Sources
* @description Reusable Workflow that pass user-controlled data to their output variables.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id actions/reusable-workflow-sources
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
import actions
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource and
not source instanceof DataFlow::ParameterNode and
exists(ReusableWorkflowStmt w | w.getAChildNode*() = source.asExpr())
}
predicate isSink(DataFlow::Node sink) {
exists(ReusableWorkflowStmt w | w.getOutputsStmt().getOutputExpr(_) = sink.asExpr())
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
allowImplicitRead(node, set)
or
isSink(node) and
set instanceof DataFlow::FieldContent
}
}
module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Source"

View File

@@ -0,0 +1,37 @@
/**
* @name Reusable Workflows Summaries
* @description Reusable workflow that pass user-controlled data to their output variables.
* @kind path-problem
* @problem.severity warning
* @security-severity 9.3
* @precision high
* @id actions/reusable-workflow-summaries
* @tags actions
* model-generator
* external/cwe/cwe-020
*/
import actions
import codeql.actions.TaintTracking
import codeql.actions.dataflow.FlowSources
import codeql.actions.dataflow.ExternalFlow
private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(ReusableWorkflowStmt w | w.getInputsStmt().getInputExpr(_) = source.asExpr())
}
predicate isSink(DataFlow::Node sink) {
exists(ReusableWorkflowStmt w | w.getOutputsStmt().getOutputExpr(_) = sink.asExpr())
}
}
module MyFlow = TaintTracking::Global<MyConfig>;
import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where
MyFlow::flowPath(source, sink) and
source.getNode().getLocation().getFile() = sink.getNode().getLocation().getFile()
select sink.getNode(), source, sink, "Summary"

View File

@@ -20,7 +20,7 @@ import codeql.actions.dataflow.ExternalFlow
private class ExpressionInjectionSink extends DataFlow::Node {
ExpressionInjectionSink() {
exists(RunExpr e | e.getScriptExpr() = this.asExpr()) or
sinkNode(this, "expression-injection")
externallyDefinedSink(this, "expression-injection")
}
}
@@ -37,5 +37,4 @@ import MyFlow::PathGraph
from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Potential injection from the ${{ " + sink.getNode().asExpr().(ExprAccessExpr).getExpression() +
" }}, which may be controlled by an external user."
"Potential expression injection, which may be controlled by an external user."

View File

@@ -0,0 +1,19 @@
- description: Standard Code Scanning queries for Actions
- queries: .
- include:
kind:
- problem
- path-problem
tags contain:
- security
- maintainability
- include:
kind:
- diagnostic
- exclude:
tags contain:
- experimental
- testing

View File

@@ -0,0 +1,8 @@
- description: Queries to model composite actions
- queries: .
- include:
kind:
- path-problem
tags contain:
- model-generator

View File

@@ -1,6 +1,6 @@
---
library: false
name: codeql/actions-queries
name: githubsecuritylab/actions-queries
version: 0.0.1
groups:
- actions
@@ -9,6 +9,6 @@ suites: codeql-suites
extractor: yaml
defaultSuiteFile: codeql-suites/actions-code-scanning.qls
dependencies:
codeql/actions-all: ${workspace}
githubsecuritylab/actions-all: ${workspace}
warnOnImplicitThis: true
tests: test

View File

@@ -8,17 +8,20 @@ jobs:
uses: octo-org/this-repo/.github/workflows/reusable_workflow.yml@172239021f7ba04fe7327647b213799853a9eb89
with:
config-path: ${{ github.event.pull_request.head.ref }}
secrets: inherit
call2:
uses: ./.github/workflows/reusable_workflow.yml
with:
config-path: ${{ github.event.pull_request.head.ref }}
secrets: inherit
call3:
uses: octo-org/another-repo/.github/workflows/workflow.yml@v1
uses: octo-org/summary-repo/.github/workflows/workflow.yml@v1
with:
config-path: ${{ github.event.pull_request.head.ref }}
call4:
uses: octo-org/source-repo/.github/workflows/workflow.yml@v1
call5:
uses: octo-org/sink-repo/.github/workflows/workflow.yml@v1
with:
config-path: ${{ github.event.pull_request.head.ref }}
secrets: inherit
job1:
runs-on: ubuntu-latest
@@ -36,3 +39,8 @@ jobs:
needs: call3
steps:
- run: echo ${{ needs.call3.outputs.workflow-output }}
job4:
runs-on: ubuntu-latest
needs: call4
steps:
- run: echo ${{ needs.call4.outputs.workflow-output }}

View File

@@ -1,47 +0,0 @@
run-name: Cleanup ${{ github.head_ref }}
on:
pull_request_target:
types: labeled
paths:
- "images/**"
jobs:
clean_ci:
name: Clean CI runs
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: pwsh
run: |
$startDate = Get-Date -UFormat %s
$workflows = @("macos11", "macos12", "ubuntu2004", "ubuntu2204", "windows2019", "windows2022")
while ($true) {
$continue = $false
foreach ($wf in $workflows) {
$skippedCommand = "gh run list --workflow ${wf}.yml --branch ${{ github.event.pull_request.head.ref }} --repo ${{ github.repository }} --status skipped --json databaseId"
$skippedIds = Invoke-Expression -Command $skippedCommand | ConvertFrom-Json | ForEach-Object { $_.databaseId }
$skippedIds | ForEach-Object {
$deleteCommand = "gh run delete --repo ${{ github.repository }} $_"
Invoke-Expression -Command $deleteCommand
}
$pendingCommand = "gh run list --workflow ${wf}.yml --branch ${{ github.event.pull_request.head.ref }} --repo ${{ github.repository }} --status requested --json databaseId --template '{{ . | len }}'"
$pending = Invoke-Expression -Command $pendingCommand
if ($pending -gt 0) {
Write-Host "Pending for ${wf}.yml: $pending run(s)"
$continue = $true
}
}
if ($continue -eq $false) {
Write-Host "All done, exiting"
break
}
$curDate = Get-Date -UFormat %s
if (($curDate - $startDate) -gt 60) {
Write-Host "Reached timeout, exiting"
break
}
Write-Host "Waiting 5 seconds..."
Start-Sleep -Seconds 5

View File

@@ -14,42 +14,24 @@ jobs:
- name: Extract and Clean Initial URL
id: extract-url
env:
BODY: ${{ github.event.comment.body }}
run: |
INITIAL_URL=$(echo "${{ github.event.comment.body }}" | grep -o 'https://github.com/github/release-assets/assets/[^ >]*')
echo "Cleaned Initial URL: $INITIAL_URL"
echo "::set-output name=initial_url::$INITIAL_URL"
echo "::set-output name=initial_url::$BODY"
- name: Get Redirected URL with Debugging
id: curl
env:
INITIAL_URL: ${{ steps.extract-url.outputs.initial_url }}
run: |
REDIRECTED_URL=$(curl -L -o /dev/null -w %{url_effective} -sS "${{ steps.extract-url.outputs.initial_url }}")
echo "Curl Command Executed"
echo "Redirected URL: $REDIRECTED_URL"
echo "::set-output name=redirected_url::$REDIRECTED_URL"
echo "redirected_url=$(echo $INITIAL_URL)" >> $GITHUB_OUTPUT
- name: Trim URL after PNG
id: trim-url
env:
REDIRECTED_URL: ${{ steps.curl.outputs.redirected_url }}
run: |
TRIMMED_URL=$(echo "${{ steps.curl.outputs.redirected_url }}" | sed 's/\(.*\.png\).*/\1/')
echo "Trimmed URL: $TRIMMED_URL"
echo "::set-output name=trimmed_url::$TRIMMED_URL"
- name: Output Final Trimmed URL
run: |
echo "Final Trimmed Image URL: ${{ steps.trim-url.outputs.trimmed_url }}"
echo "trimmed_url=$(echo $REDIRECTED_URL)" >> "$GITHUB_OUTPUT"
- name: Update Comment with New URL
run: |
COMMENT_URL="${{ github.event.comment.url }}"
NEW_COMMENT_BODY="Use this link to include this asset in your changelog: ${{ steps.trim-url.outputs.trimmed_url }}"
ORIGINAL_COMMENT_BODY="${{ github.event.comment.body }}"
UPDATED_COMMENT="${ORIGINAL_COMMENT_BODY} 👀 ${NEW_COMMENT_BODY}"
PAYLOAD=$(jq -n --arg body "$UPDATED_COMMENT" '{"body": $body}')
curl -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"${COMMENT_URL}" \
-d "$PAYLOAD"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,61 +0,0 @@
name: Image URL Processing
on:
issue_comment:
types: [created]
jobs:
process-image-url:
runs-on: ubuntu-latest
if: contains(github.event.comment.body, 'https://github.com/github/release-assets/assets/')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Extract and Clean Initial URL
id: extract-url
env:
BODY: ${{ github.event.comment.body }}
run: |
INITIAL_URL=$(echo "$BODY" | grep -o 'https://github.com/github/release-assets/assets/[^ >]*')
echo "Cleaned Initial URL: $INITIAL_URL"
echo "::set-output name=initial_url::$INITIAL_URL"
- name: Get Redirected URL with Debugging
id: curl
env:
INITIAL_URL: ${{ steps.extract-url.outputs.initial_url }}
run: |
REDIRECTED_URL=$(curl -L -o /dev/null -w %{url_effective} -sS "$INITIAL_URL")
echo "Curl Command Executed"
echo "Redirected URL: $REDIRECTED_URL"
echo "::set-output name=redirected_url::$REDIRECTED_URL"
- name: Trim URL after PNG
id: trim-url
env:
REDIRECTED_URL: ${{ steps.curl.outputs.redirected_url }}
run: |
TRIMMED_URL=$(echo "$REDIRECTED_URL" | sed 's/\(.*\.png\).*/\1/')
echo "Trimmed URL: $TRIMMED_URL"
echo "::set-output name=trimmed_url::$TRIMMED_URL"
- name: Output Final Trimmed URL
run: |
echo "Final Trimmed Image URL: ${{ steps.trim-url.outputs.trimmed_url }}"
- name: Update Comment with New URL
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMENT_URL: ${{ github.event.comment.url }}
ORIGINAL_COMMENT_BODY: ${{ github.event.comment.body }}
run: |
NEW_COMMENT_BODY="Use this link to include this asset in your changelog: ${{ steps.trim-url.outputs.trimmed_url }}"
UPDATED_COMMENT="${ORIGINAL_COMMENT_BODY} 👀 ${NEW_COMMENT_BODY}"
PAYLOAD=$(jq -n --arg body "$UPDATED_COMMENT" '{"body": $body}')
curl -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"${COMMENT_URL}" \
-d "$PAYLOAD"

View File

@@ -1,27 +0,0 @@
name: Image URL Processing
on:
issue_comment:
types: [created]
jobs:
process-image-url:
runs-on: ubuntu-latest
if: contains(github.event.comment.body, 'https://github.com/github/release-assets/assets/')
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Extract and Clean Initial URL
id: source
env:
BODY: ${{ github.event.comment.body }}
run: |
INITIAL_URL=$(echo "$BODY" | grep -o 'https://github.com/github/release-assets/assets/[^ >]*')
echo "Cleaned Initial URL: $INITIAL_URL"
echo "::set-output name=initial_url::$INITIAL_URL"
- name: Get Redirected URL with Debugging
id: sink
run: |
echo ${{ steps.source.outputs.initial_url }}

View File

@@ -5,12 +5,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: source
- id: summary
uses: mad9000/actions-find-and-replace-string@3
with:
source: ${{ github.event.head_commit.message }}
find: 'foo'
replace: ''
- id: sink
- id: flow
run: |
echo "${{steps.source.outputs.value}}"
echo "${{steps.summary.outputs.value}}"
- id: no-flow
run: |
echo "${{steps.summary.outputs.foo}}"

View File

@@ -33,4 +33,10 @@ jobs:
echo "$file was changed"
done
- name: List all changed files
id: no-flow
run: |
for file in ${{ steps.source.outputs.all_changed_files_count }}; do
echo "$file was changed"
done

View File

@@ -22,7 +22,9 @@ jobs:
run: |
Write-Output "::set-output name=MSG::$ENV{BODY}"
- id: step2
run: echo "test=${{steps.step1.outputs.MSG}}" >> "$GITHUB_OUTPUT"
env:
MSG: ${{steps.step1.outputs.MSG}}
run: echo "test=$MSG" >> "$GITHUB_OUTPUT"
job2:
runs-on: ubuntu-latest
@@ -32,5 +34,4 @@ jobs:
needs: job1
steps:
- env:
run: echo ${{needs.job1.outputs.job_output}}
- run: echo ${{needs.job1.outputs.job_output}}