├── .gitignore
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── fixme
├── images
├── 00-repo-security-tab.png
├── 01-repo-secruity-setup-code-scanning.png
├── 02-repo-security-setup-codeql-workflow.png
├── 03-actions-sample-workflow.png
├── 04-actions-sample-events.png
├── 05-actions-completed.png
├── 06-security-codeql-alert.png
├── 07-security-codeql-show-more.png
├── 08-security-codeql-full-desc.png
├── 09-security-codeql-show-paths.png
├── 10-security-codeql-show-paths-details.png
├── 11-fix-source-code.png
├── 12-fix-pr-in-progress.png
├── 13-fix-pr-done.png
├── 14-fix-detail.png
├── 15-fixed-alert.png
├── 16-fix-history.png
├── 17-fork-repo.png
├── 18-create-vulnerable-pr.png
├── 19-vulnerabiltliy-detail.png
└── 20-files-changed-vulnerabilities.png
├── server
├── __init__.py
├── __main__.py
├── models
│ ├── __init__.py
│ └── books.py
├── routes.py
└── webapp.py
└── templates
└── books.html
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.db
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | pip-wheel-metadata/
27 | share/python-wheels/
28 | *.egg-info/
29 | .installed.cfg
30 | *.egg
31 | MANIFEST
32 |
33 | # PyInstaller
34 | # Usually these files are written by a python script from a template
35 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
36 | *.manifest
37 | *.spec
38 |
39 | # Installer logs
40 | pip-log.txt
41 | pip-delete-this-directory.txt
42 |
43 | # Unit test / coverage reports
44 | htmlcov/
45 | .tox/
46 | .nox/
47 | .coverage
48 | .coverage.*
49 | .cache
50 | nosetests.xml
51 | coverage.xml
52 | *.cover
53 | *.py,cover
54 | .hypothesis/
55 | .pytest_cache/
56 |
57 | # Translations
58 | *.mo
59 | *.pot
60 |
61 | # Django stuff:
62 | *.log
63 | local_settings.py
64 | db.sqlite3
65 | db.sqlite3-journal
66 |
67 | # Flask stuff:
68 | instance/
69 | .webassets-cache
70 |
71 | # Scrapy stuff:
72 | .scrapy
73 |
74 | # Sphinx documentation
75 | docs/_build/
76 |
77 | # PyBuilder
78 | target/
79 |
80 | # Jupyter Notebook
81 | .ipynb_checkpoints
82 |
83 | # IPython
84 | profile_default/
85 | ipython_config.py
86 |
87 | # pyenv
88 | .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
98 | __pypackages__/
99 |
100 | # Celery stuff
101 | celerybeat-schedule
102 | celerybeat.pid
103 |
104 | # SageMath parsed files
105 | *.sage.py
106 |
107 | # Environments
108 | .env
109 | .venv
110 | env/
111 | venv/
112 | ENV/
113 | env.bak/
114 | venv.bak/
115 |
116 | # Spyder project settings
117 | .spyderproject
118 | .spyproject
119 |
120 | # Rope project settings
121 | .ropeproject
122 |
123 | # mkdocs documentation
124 | /site
125 |
126 | # mypy
127 | .mypy_cache/
128 | .dmypy.json
129 | dmypy.json
130 |
131 | # Pyre type checker
132 | .pyre/
133 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 OctoDemo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [packages]
7 | flask = "*"
8 | python-dotenv = "*"
9 |
10 | [dev-packages]
11 |
12 | [requires]
13 | python_version = "3.8"
14 |
--------------------------------------------------------------------------------
/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "069f33d2dc75b242fa5ee44daf090c80831812dc6cc59824e94c22a677eac958"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.8"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {
19 | "click": {
20 | "hashes": [
21 | "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
22 | "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"
23 | ],
24 | "markers": "python_version >= '3.6'",
25 | "version": "==8.0.1"
26 | },
27 | "flask": {
28 | "hashes": [
29 | "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2",
30 | "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"
31 | ],
32 | "index": "pypi",
33 | "version": "==2.0.2"
34 | },
35 | "itsdangerous": {
36 | "hashes": [
37 | "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
38 | "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
39 | ],
40 | "markers": "python_version >= '3.6'",
41 | "version": "==2.0.1"
42 | },
43 | "jinja2": {
44 | "hashes": [
45 | "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45",
46 | "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c"
47 | ],
48 | "markers": "python_version >= '3.6'",
49 | "version": "==3.0.2"
50 | },
51 | "markupsafe": {
52 | "hashes": [
53 | "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
54 | "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
55 | "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
56 | "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
57 | "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
58 | "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
59 | "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
60 | "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
61 | "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
62 | "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
63 | "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
64 | "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
65 | "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
66 | "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
67 | "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
68 | "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
69 | "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
70 | "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
71 | "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
72 | "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
73 | "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
74 | "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
75 | "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
76 | "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
77 | "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
78 | "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
79 | "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
80 | "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
81 | "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
82 | "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
83 | "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
84 | "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
85 | "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
86 | "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
87 | "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
88 | "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
89 | "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
90 | "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
91 | "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
92 | "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
93 | "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
94 | "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
95 | "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
96 | "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
97 | "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
98 | "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
99 | "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
100 | "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
101 | "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
102 | "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
103 | "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
104 | "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
105 | "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
106 | "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
107 | ],
108 | "markers": "python_version >= '3.6'",
109 | "version": "==2.0.1"
110 | },
111 | "python-dotenv": {
112 | "hashes": [
113 | "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1",
114 | "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"
115 | ],
116 | "index": "pypi",
117 | "version": "==0.19.0"
118 | },
119 | "werkzeug": {
120 | "hashes": [
121 | "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f",
122 | "sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"
123 | ],
124 | "markers": "python_version >= '3.6'",
125 | "version": "==2.0.2"
126 | }
127 | },
128 | "develop": {}
129 | }
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Code Scanning Python Tutorial
2 |
3 | Welcome to the Code Scanning Python Tutorial! This tutorial will take you through how to set up Github Advanced Security: Code Scanning as well as interpret results that it may find. The following repository contains SQL injection vulnerability for demonstration purpose.
4 |
5 | ## Introduction
6 |
7 | Code scanning is a feature that you use to analyze the code in a GitHub repository to find security vulnerabilities and coding errors. Any problems identified by the analysis are shown in GitHub.
8 |
9 | You can use code scanning with CodeQL, a semantic code analysis engine. CodeQL treats code as data, allowing you to find potential vulnerabilities in your code with greater confidence than traditional static analyzers.
10 |
11 | This tutorial with use CodeQL Analysis with Code Scanning in order to search for vulnerabilities within your code.
12 |
13 | ## Instructions
14 |
15 |
18 |
19 | Begin by [forking this repo](https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo).
20 |
21 | NOTE: Make sure you uncheck "Copy the `main` branch only"
22 |
23 |
32 |
33 | #### Security tab
34 |
35 | Click on the `Security` tab.
36 |
37 |
38 |
60 |
61 | #### Actions Workflow
62 |
63 | The Actions Workflow file contains a number of different sections including:
64 | 1. Checking out the repository
65 | 2. Initializing the CodeQL Action
66 | 3. Running the CodeQL Analysis
67 |
68 |
78 |
79 | #### Workflow triggers
80 |
81 | There are a [number of events](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows) that can trigger a GitHub Actions workflow. In this example, the workflow will be triggered on
82 |
83 |
99 |
100 | #### GitHub Actions Progress
101 |
102 | Click `Actions` tab -> `CodeQL`
103 |
104 | Click the specific workflow run. You can view the progress of the Workflow run until the analysis completes.
105 |
106 |
114 |
115 | Once the Workflow has completed, click the `Security` tab -> ` Code Scanning Alerts`. An security alert "Query built from user-controlled sources" should be visible.
116 |
117 | #### Security Alert View
118 |
119 | Clicking on the security alert will provide details about the security alert including: Fork this repo
17 |
24 |
25 |
Enable Code Scanning
31 |
39 |
40 | #### Set up code scanning
41 |
42 | Click `Set up code scanning`.
43 |
44 |
45 |
46 | #### Setup Workflow
47 |
48 | Click the `Setup this workflow` button by CodeQL Analysis.
49 |
50 |
51 |
52 | This will create a GitHub Actions Workflow file with CodeQL already set up. Since Python is an interpreted language you do not need to add any additional compile flags. See the [documentation](https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/running-codeql-code-scanning-in-your-ci-system) if you would like to configure CodeQL Analysis with a 3rd party CI system instead of using GitHub Actions.
53 |
Actions Workflow file
59 |
69 |
70 | Click `Start Commit` -> `Commit this file` to commit the changes to _main_ branch.
71 |
Workflow triggers
77 |
84 |
85 | - push to _main_ branch
86 | - pull request to merge to _main_ branch
87 | - on schedule, at 6:33 every Thursday
88 |
89 | Setting up the new CodeQL workflow and committing it to _main_ branch in the step above will trigger the scan.
90 |
91 |
GitHub Actions Progress
97 |
98 |
107 |
108 |
Security Issues
113 |
120 |
121 |
126 |
127 |
128 | #### Security Alert Description
129 |
130 | Click `Show more` to view a full desciption of the alert including examples and links to additional information.
131 |
132 |
133 |
134 | #### Security Full Description
135 |
136 |
137 |
138 |
144 |
145 | #### Show Paths Button
146 |
147 | CodeQL Analysis is able to trace the dataflow path from source to sink and gives you the ability to view the path traversal within the alert.
148 |
149 | Click `show paths` in order to see the dataflow path that resulted in this alert.
150 |
151 |
152 |
153 | #### Show Paths View
154 |
155 |
156 |
157 |
162 |
163 | Fix the Security Alert
164 |
165 | In order to fix this specific alert, we will need to ensure parameters used in the SQL query is validated and sanitized.
166 |
167 | Click on the `Code` tab and [Edit](https://docs.github.com/en/free-pro-team@latest/github/managing-files-in-a-repository/editing-files-in-your-repository) the file [`routes.py`](./server/routes.py) in the `server` folder, replace the content with the file [`fixme`](./fixme).
168 |
169 |
170 |
171 | Click `Create a new branch for this commit and start a pull request`, name the branch `fix-sql-injection`, and create the Pull Request.
172 |
173 | #### Pull Request Status Check
174 |
175 | In the Pull Request, you will notice that the CodeQL Analysis has started as a status check. Wait until it completes.
176 |
177 |
178 |
179 | #### Security Alert Details
180 |
181 | After the Workflow has completed click on `Details` by the `Code Scanning Results / CodeQL` status check.
182 |
183 |
184 |
185 | #### Fixed Alert
186 |
187 | Notice that Code Scanning has detected that this Pull Request will fix the SQL injection vulnerability that was detected before.
188 |
189 |
190 |
191 | Merge the Pull Request. After the Pull Request has been merged, another Workflow will kick off to scan the repository for any vulnerabilties.
192 |
193 | #### Closed Security Alerts
194 |
195 | After the final Workflow has completed, navigate back to the `Security` tab and click `Closed`. Notice that the **Query built from user-controlled sources** security alert now shows up as a closed issue.
196 |
197 |
198 |
199 | #### Traceability
200 |
201 | Click on the security alert and notice that it details when the fix was made, by whom, and the specific commit. This provides full traceability to detail when and how a security alert was fixed and exactly what was changed to remediate the issue.
202 |
203 |
204 |
205 |
211 |
212 | Now let's explore the typical developer view when introducing a vulnerability.
213 |
214 | A branch called `new-feature` introduces a new feature but also security vulnerabilities. Open a Pull Request comparing `new-feature` to `main`:
215 |
216 | 1. Go to the Pull Request tab
217 | 2. Select "New Pull Request"
218 | 3. Create the PR with
219 | - `base repository:
226 |
227 | #### Pull Request Status Check
228 |
229 | In the Pull Request, you will notice that the CodeQL Analysis has started as a status check again. Wait until it completes.
230 |
231 | #### Security Alert Details
232 |
233 | After the Workflow has completed click on `Details` by the `Code Scanning Results / CodeQL` status check.
234 |
235 | #### Security Alert
236 |
237 | Notice that Code Scanning has detected that this Pull Request will introduce 2 medium-severity vulnerabilties
238 |
239 |
240 |
241 | #### 'Files Changed' tab
242 |
243 | Click on the "Files Changed" tab of the PR. Scroll down and notice the Advanced Security annotations for new vulnerabilities.
244 |
245 | You have the ability to dismiss, dive deeper into, or comment on these alerts directly from here.
246 |
247 |
248 |
249 | As a developer, this is where you would be interacting with Code Scanning
250 |
251 |