Real scan / 2026-10-07真實掃描 / 2026-10-07

Fix it, then check again.修好之後,再檢查一次。

We scanned a small demo project, fixed some of its problems and checked it again. The app compared the two scans.我們掃描一個小型示範專案,修正其中幾個問題後再檢查一次,由程式比較兩次掃描的結果。

These improvements are included in v0.5.0. This example was made with development builds after v0.4.1: the scans with commit bca90a8, the comparison screenshot with dff42c2, and the reports and other screenshots with e663b0a. v0.4.1 does not have step 4, choosing the fixed folder again (it scans the copy saved when the folder was first chosen), the comparison at the top of the Scan 2 report, or problems that combine related findings: it lists every finding on its own.這些改進已納入 v0.5.0。本範例使用 v0.4.1 之後的開發版本製作:掃描使用 commit bca90a8,比較結果截圖使用 dff42c2,報告與其他截圖使用 e663b0a。v0.4.1 沒有第 4 步「重新選擇修正後的資料夾」(它掃描的是第一次選擇資料夾時保存的副本),沒有第 2 次掃描報告開頭的比較,也不會把相關的發現合併成一個問題,而是逐筆列出。

01

A small API with planted problems一個刻意放入問題的小型 API

inventory-api-demo is a small Flask service written for this demo. It has five planted problems:inventory-api-demo 是為這次示範寫的小型 Flask 服務,刻意放入五種問題:

02

First scan: 13 problems第一次掃描:13 個問題

The app scanned the folder with eight tools in about 13 minutes on the test computer. All eight completed. The report shows their 26 findings as 13 problems, 6 of them Critical or High, and starts with the vulnerable PyYAML version.程式用八個工具掃描這個資料夾,在測試電腦上約 13 分鐘完成,八個工具都跑完。報告把它們的 26 筆發現整理成 13 個問題,其中 6 個是重大或高風險,並建議先處理有弱點的 PyYAML 版本。

Results for Scan 1: one asset with 13 problems, and the first three to fix: the Critical PyYAML 5.3.1 package, a High Dockerfile without a USER instruction and a High private key in a file. 第 1 次掃描的結果:一個資產有 13 個問題,最先處理的三項是重大的 PyYAML 5.3.1 套件、高風險的 Dockerfile 未指定 USER,以及高風險的檔案中私鑰。
Results for Scan 1: what to fix first.第 1 次掃描的結果:先處理哪些問題。
Tools and versions工具與版本

Checkov 3.3.13 · Gitleaks 8.30.1 · Grype 0.117.0 · KICS 2.1.20 · Semgrep 1.174.0 · Syft 1.51.0 · Trivy 0.74.0 · TruffleHog 3.97.0. Syft lists the software packages; it does not report problems. Both scans used the same versions.Checkov 3.3.13 · Gitleaks 8.30.1 · Grype 0.117.0 · KICS 2.1.20 · Semgrep 1.174.0 · Syft 1.51.0 · Trivy 0.74.0 · TruffleHog 3.97.0。Syft 負責列出軟體套件,不回報問題。兩次掃描使用相同版本。

03

The fix修正

One commit fixed four of the five problems and left the shell call alone. It also turned on Flask debug mode on purpose, to see whether the check catches a new problem.一個 commit 修正了五種問題中的四種,shell 呼叫則維持原樣;另外刻意開啟 Flask 的除錯模式,看看檢查能不能抓到新問題。

deploy/deploy_key    deleted
.gitignore           added: deploy/*_key

--- a/app.py
+++ b/app.py
 def import_inventory():
-    # Accepts an inventory list as YAML.
-    items = yaml.load(request.data, Loader=yaml.Loader)
-    return jsonify({"imported": len(items or [])})
+    # Accepts an inventory list as YAML. safe_load builds only plain data.
+    items = yaml.safe_load(request.data)
+    if not isinstance(items, list):
+        return jsonify({"error": "expected a list"}), 400
+    return jsonify({"imported": len(items)})
 ...
 if __name__ == "__main__":
-    app.run(host="127.0.0.1", port=8080)
+    app.run(host="127.0.0.1", port=8080, debug=True)

--- a/requirements.txt
+++ b/requirements.txt
-PyYAML==5.3.1
+PyYAML==6.0.2

--- a/Dockerfile
+++ b/Dockerfile
+RUN useradd --create-home --uid 10001 app
+USER app

04

Choose the fixed folder again重新選擇修正後的資料夾

A scan reads a copy of the folder saved when you choose it. Before checking again, choose the folder again in My scans → Check fixes. Here the new copy had 3 files changed, 1 added and 1 removed.掃描讀取的是選擇資料夾時保存的副本。再次檢查前,先到「我的掃描 → 確認修復」重新選擇資料夾。這次的新副本有 3 個檔案變更、1 個新增、1 個移除。

Check fixes with Scan 1 as the baseline. The step Choose the fixed folder lists the folder as not chosen again yet, and the start button waits until it is. 確認修復以第 1 次掃描為比較基準。「選擇修正後的資料夾」步驟顯示資料夾尚未重新選擇,開始按鈕要等選好後才能使用。
Check fixes asks for the fixed folder before it starts.確認修復會先請你選擇修正後的資料夾,再開始檢查。

05

What changed比較結果

The same eight tools ran again, in about 12 minutes. Every check completed in both scans with the same tool versions, so every problem could be compared.同樣的八個工具再跑一次,約 12 分鐘。兩次掃描的每項檢查都已完成,工具版本也相同,所以每個問題都能比較。

Check fixes comparison: folder copies e35c4d74be02 to 98c8d9af6838; 6 no longer observed, 7 still present, 1 new, 0 verification incomplete. 確認修復的比較結果:資料夾副本 e35c4d74be02 → 98c8d9af6838;6 個這次沒有再看到、7 個仍然存在、1 個新出現、0 個驗證未完成。
The comparison names the two folder copies it read.比較結果會列出它讀取的兩份資料夾副本。
Comparison outcome by problem依問題列出的比較結果
Outcome結果 Problems問題 What they were內容
No longer observed這次沒有再看到 6 Private key: 1 problem from 5 detections (Gitleaks, TruffleHog, Semgrep ×3). PyYAML 5.3.1: 1 from 2 (Grype, Trivy). Unsafe YAML loading: 1 (Semgrep). Container runs as root: 3, one each from Checkov, KICS and Semgrep.私鑰:1 個問題,來自 5 筆偵測(Gitleaks、TruffleHog、Semgrep ×3)。PyYAML 5.3.1:1 個,來自 2 筆(Grype、Trivy)。不安全的 YAML 載入:1 個(Semgrep)。容器以 root 執行:3 個,Checkov、KICS、Semgrep 各一個。
Still present仍然存在 7 Shell call: 1 problem from 5 Semgrep detections; the code moved from line 19 to line 21. Flask and requests advisories: 4, each reported by Grype and Trivy. No container health check: 2 (Checkov, KICS).shell 呼叫:1 個問題,來自 5 筆 Semgrep 偵測,程式碼從第 19 行移到第 21 行。Flask 與 requests 的安全公告:4 個,每個都由 Grype 與 Trivy 回報。容器沒有健康檢查:2 個(Checkov、KICS)。
New新出現 1 Flask debug mode (Semgrep, app.py line 26).Flask 除錯模式(Semgrep,app.py 第 26 行)。
Verification incomplete驗證未完成 0 —
The still-present shell-call problem, High, from 5 original findings: the same rule still finds this problem in the same file and only its line moved. The open list says each of the 5 findings moved from line 19 to line 21. 仍然存在的 shell 呼叫問題,高風險,來自 5 筆原始發現:同一條規則在同一個檔案仍找到這個問題,只是行號改變。展開的清單顯示 5 筆發現都從第 19 行移到第 21 行。
The shell call moved two lines down. It stays still present; only its line moved.shell 呼叫往下移了兩行。它仍然存在,只是行號改變。
The one new problem: Semgrep detected a Flask app with debug=True, before not observed, after Medium. 唯一新出現的問題:Semgrep 偵測到 Flask 應用程式開啟 debug=True,修復前沒有觀察到,修復後為中風險。
Debug mode, turned on in the fix, shows up as new.修正時開啟的除錯模式,被列為新出現的問題。

06

What this demo does not show這次沒有涵蓋的部分

07

Read both reports閱讀兩次掃描的報告

Both reports were saved from the app with sensitive identifiers hidden, so the asset is named Asset 1.兩份報告都從程式儲存,並遮罩敏感識別資訊,所以資產名稱顯示為「Asset 1」。

Scan 1 / before the fix第 1 次掃描 / 修正前

13 problems13 個問題

From 26 findings: 1 Critical, 5 High, 3 Medium, 2 Low and 2 without a scanner rating.來自 26 筆發現:1 個重大、5 個高、3 個中、2 個低,另有 2 個掃描工具未評等。

Scan 2 / after the fix第 2 次掃描 / 修正後

8 problems8 個問題

From 16 findings: 0 Critical, 1 High, 4 Medium, 2 Low and 1 without a scanner rating. The report opens with what changed since Scan 1.來自 16 筆發現:0 個重大、1 個高、4 個中、2 個低,另有 1 個掃描工具未評等。報告開頭先說明與第 1 次掃描相比的變化。

How these files were made: README · File checksums: SHA256SUMS.txt製作方式:說明文件 · 檔案雜湊值:SHA256SUMS.txt