@vnptnan/gate 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +51 -2
- package/VERSION +1 -0
- package/bin/cli.js +226 -0
- package/ci/.gitlab-ci.yml +41 -0
- package/cli/vnptnan-gate +90 -0
- package/cli/vnptnan-gate.cmd +9 -0
- package/engine/gate-deps.sh +110 -0
- package/engine/gate-lib.sh +285 -0
- package/engine/gate-scan.sh +155 -0
- package/engine/prompt-check.sh +77 -0
- package/gate.conf +13 -0
- package/hooks/commit-msg +10 -0
- package/hooks/pre-commit +7 -0
- package/hooks/pre-push +7 -0
- package/installer/install-server.sh +33 -0
- package/installer/install.ps1 +80 -0
- package/installer/uninstall.ps1 +15 -0
- package/package.json +44 -3
- package/policy.json +4 -0
- package/rules/ai-tools.rules +15 -0
- package/rules/gate.rules +75 -0
- package/rules/packages.rules +18 -0
- package/server/pre-receive +13 -0
- package/tools/lint-rules.sh +37 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Cai VNPTNAN_GATE len may dev Windows. Chay bang quyen admin (installer tu xin UAC).
|
|
2
|
+
# powershell -NoProfile -ExecutionPolicy Bypass -File installer\install.ps1 [-WhatIf]
|
|
3
|
+
# Viec lam: copy bo cong cu vao %ProgramData%\VNPTNAN_GATE\current (chi admin ghi duoc), dang ky hook pre-commit,
|
|
4
|
+
# pre-push, commit-msg o git config cap he thong bang co che hook.<ten>.event/command (Git for Windows >= 2.54, cung
|
|
5
|
+
# co che VNPTNAN_HARNESS dang dung cho hook.vnptnan-guard, nhung TEN KHAC nen hai ben khong de len nhau),
|
|
6
|
+
# them cli vao PATH may, tao thu muc log. Khong dong vao bat ky cau hinh nao cua VNPTNAN_HARNESS.
|
|
7
|
+
# Keep this file ASCII-only (Windows PowerShell 5.1).
|
|
8
|
+
[CmdletBinding(SupportsShouldProcess = $true)]
|
|
9
|
+
param(
|
|
10
|
+
[string]$InstallRoot = (Join-Path $env:ProgramData 'VNPTNAN_GATE'),
|
|
11
|
+
[string]$Mode = 'enforce' # enforce | audit (thi diem 2 tuan dau: audit)
|
|
12
|
+
)
|
|
13
|
+
$ErrorActionPreference = 'Stop'
|
|
14
|
+
$source = Split-Path -Parent $PSScriptRoot
|
|
15
|
+
|
|
16
|
+
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
17
|
+
if (-not $isAdmin -and -not $WhatIfPreference) {
|
|
18
|
+
$args = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $PSCommandPath, '-InstallRoot', $InstallRoot, '-Mode', $Mode)
|
|
19
|
+
Start-Process powershell -Verb RunAs -ArgumentList $args -Wait
|
|
20
|
+
exit $LASTEXITCODE
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function Find-Git {
|
|
24
|
+
foreach ($c in @((Join-Path $env:ProgramFiles 'Git\cmd\git.exe'), (Join-Path $env:LOCALAPPDATA 'Programs\Git\cmd\git.exe'))) {
|
|
25
|
+
if (Test-Path $c) { return $c }
|
|
26
|
+
}
|
|
27
|
+
$g = Get-Command git -ErrorAction SilentlyContinue
|
|
28
|
+
if ($g) { return $g.Source }
|
|
29
|
+
throw 'Can Git for Windows (>= 2.54).'
|
|
30
|
+
}
|
|
31
|
+
$git = Find-Git
|
|
32
|
+
$ver = (& $git --version) -replace '[^0-9.]', '' -split '\.'
|
|
33
|
+
if ([int]$ver[0] -lt 2 -or ([int]$ver[0] -eq 2 -and [int]$ver[1] -lt 54)) {
|
|
34
|
+
Write-Warning "Git $($ver -join '.') chua ho tro hook theo config (can >= 2.54). Se chi copy bo cong cu; moi repo chay: vnptnan-gate install-hooks"
|
|
35
|
+
$configHooks = $false
|
|
36
|
+
} else { $configHooks = $true }
|
|
37
|
+
|
|
38
|
+
$current = Join-Path $InstallRoot 'current'
|
|
39
|
+
if ($PSCmdlet.ShouldProcess($current, 'Copy bo cong cu')) {
|
|
40
|
+
New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null
|
|
41
|
+
if (Test-Path $current) { Remove-Item -Recurse -Force $current }
|
|
42
|
+
Copy-Item -Recurse -Force $source $current
|
|
43
|
+
Remove-Item -Recurse -Force (Join-Path $current '.git') -ErrorAction SilentlyContinue
|
|
44
|
+
# Admin va SYSTEM ghi, nguoi dung chi doc va chay: AI khong sua duoc rule tren may dev.
|
|
45
|
+
$acl = Get-Acl $InstallRoot
|
|
46
|
+
$acl.SetAccessRuleProtection($true, $false)
|
|
47
|
+
foreach ($id in 'BUILTIN\Administrators', 'NT AUTHORITY\SYSTEM') {
|
|
48
|
+
$acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($id, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')))
|
|
49
|
+
}
|
|
50
|
+
$acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Users', 'ReadAndExecute', 'ContainerInherit,ObjectInherit', 'None', 'Allow')))
|
|
51
|
+
Set-Acl $InstallRoot $acl
|
|
52
|
+
# Che do: ghi vao gate.conf cua ban cai (dang ky thi diem audit)
|
|
53
|
+
$conf = Join-Path $current 'gate.conf'
|
|
54
|
+
(Get-Content $conf) -replace '^MODE=.*', "MODE=$Mode" | Set-Content -Encoding ascii $conf
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
$bashPath = ($current -replace '\\', '/')
|
|
58
|
+
if ($configHooks) {
|
|
59
|
+
foreach ($h in @(@{ Name = 'vnptnan-gate-commit'; Event = 'pre-commit'; File = 'pre-commit' },
|
|
60
|
+
@{ Name = 'vnptnan-gate-push'; Event = 'pre-push'; File = 'pre-push' },
|
|
61
|
+
@{ Name = 'vnptnan-gate-msg'; Event = 'commit-msg'; File = 'commit-msg' })) {
|
|
62
|
+
if ($PSCmdlet.ShouldProcess("git config --system hook.$($h.Name)", 'Dang ky hook')) {
|
|
63
|
+
& $git config --system --replace-all "hook.$($h.Name).event" $h.Event
|
|
64
|
+
& $git config --system --replace-all "hook.$($h.Name).command" "sh '$bashPath/hooks/$($h.File)'"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if ($PSCmdlet.ShouldProcess('PATH (Machine)', 'Them cli')) {
|
|
70
|
+
$cli = Join-Path $current 'cli'
|
|
71
|
+
$path = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
72
|
+
if ($path -notlike "*$cli*") { [Environment]::SetEnvironmentVariable('Path', "$path;$cli", 'Machine') }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ($PSCmdlet.ShouldProcess((Join-Path $env:ProgramData 'VNPTNAN_GATE\logs'), 'Tao thu muc log dung chung')) {
|
|
76
|
+
New-Item -ItemType Directory -Force -Path (Join-Path $InstallRoot 'logs') | Out-Null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
Write-Host "Da cai VNPTNAN_GATE $(Get-Content (Join-Path $current 'VERSION')) tai $current (MODE=$Mode)."
|
|
80
|
+
Write-Host 'Mo terminal moi va chay: vnptnan-gate doctor'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Go VNPTNAN_GATE khoi may dev. Chay bang quyen admin. Khong dong vao cau hinh cua VNPTNAN_HARNESS.
|
|
2
|
+
# Keep this file ASCII-only (Windows PowerShell 5.1).
|
|
3
|
+
param([string]$InstallRoot = (Join-Path $env:ProgramData 'VNPTNAN_GATE'))
|
|
4
|
+
$ErrorActionPreference = 'Continue'
|
|
5
|
+
$git = (Get-Command git -ErrorAction SilentlyContinue).Source
|
|
6
|
+
if ($git) {
|
|
7
|
+
foreach ($n in 'vnptnan-gate-commit', 'vnptnan-gate-push', 'vnptnan-gate-msg') {
|
|
8
|
+
& $git config --system --remove-section "hook.$n" 2>$null
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
$cli = Join-Path $InstallRoot 'current\cli'
|
|
12
|
+
$path = [Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
13
|
+
[Environment]::SetEnvironmentVariable('Path', (($path -split ';' | Where-Object { $_ -and $_ -ne $cli }) -join ';'), 'Machine')
|
|
14
|
+
if (Test-Path (Join-Path $InstallRoot 'current')) { Remove-Item -Recurse -Force (Join-Path $InstallRoot 'current') }
|
|
15
|
+
Write-Host 'Da go VNPTNAN_GATE. Log cu van con trong %LOCALAPPDATA%\VNPTNAN_GATE de doi chieu.'
|
package/package.json
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vnptnan/gate",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Cổng kiểm soát an toàn bảo mật thông tin khi dùng AI trong phát triển phần mềm: chặn secret, dữ liệu cá nhân, package bịa ở prompt, commit, push và máy chủ GitLab. Cài: npx @vnptnan/gate",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"git-hooks",
|
|
7
|
+
"secret-scanning",
|
|
8
|
+
"ai-coding",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"codex",
|
|
11
|
+
"gitlab",
|
|
12
|
+
"pre-receive",
|
|
13
|
+
"security"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/untilyou58/vnpt-gate.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/untilyou58/vnpt-gate#readme",
|
|
21
|
+
"bin": {
|
|
22
|
+
"vnptnan-gate-setup": "bin/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin",
|
|
26
|
+
"engine",
|
|
27
|
+
"rules",
|
|
28
|
+
"hooks",
|
|
29
|
+
"cli",
|
|
30
|
+
"installer",
|
|
31
|
+
"server",
|
|
32
|
+
"ci",
|
|
33
|
+
"tools/lint-rules.sh",
|
|
34
|
+
"gate.conf",
|
|
35
|
+
"policy.json",
|
|
36
|
+
"VERSION",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=16.7"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"registry": "https://registry.npmjs.org/",
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
6
47
|
}
|
package/policy.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Danh mục công cụ AI được phép dùng trong phát triển phần mềm tại Trung tâm. Đây là phụ lục của Bộ quy tắc sử dụng AI.
|
|
2
|
+
# Engine không đọc file này; CLI "vnptnan-gate tools" in ra để dev tra cứu. Sửa qua merge request có lead và ATTT duyệt.
|
|
3
|
+
#
|
|
4
|
+
# Mỗi dòng, ngăn bằng TAB: tool trạng-thái loại-tài-khoản dữ-liệu-tối-đa ghi-chú
|
|
5
|
+
# trạng-thái: allowed (được dùng), pilot (thí điểm, có danh sách người dùng), denied (cấm)
|
|
6
|
+
# dữ-liệu-tối-đa: mức phân loại cao nhất được đưa vào công cụ (xem Bộ quy tắc, mục 4): C0 công khai, C1 nội bộ, C2 hạn chế, C3 mật
|
|
7
|
+
claude-code allowed tài khoản tổ chức, không dùng dữ liệu để huấn luyện C2 Cài VNPTNAN_HARNESS + VNPTNAN_GATE. Mã nguồn dự án được phép; không đưa dữ liệu khách hàng thật.
|
|
8
|
+
codex allowed tài khoản tổ chức C2 Như trên. Hook của Codex chặn thay vì hỏi.
|
|
9
|
+
antigravity allowed tài khoản tổ chức C2 Như trên.
|
|
10
|
+
github-copilot pilot tài khoản tổ chức C2 Chỉ khi dự án dùng GitHub; chưa có hook Harness.
|
|
11
|
+
chatgpt-web allowed tài khoản tổ chức hoặc cá nhân đã tắt "cải thiện mô hình" C1 Chỉ hỏi đáp chung, không dán mã nguồn dự án và không dán dữ liệu khách hàng.
|
|
12
|
+
claude-web allowed tài khoản tổ chức hoặc cá nhân C1 Như chatgpt-web.
|
|
13
|
+
gemini-web allowed tài khoản tổ chức hoặc cá nhân C1 Như chatgpt-web.
|
|
14
|
+
deepseek-web denied - - Máy chủ ngoài phạm vi kiểm soát, điều khoản dữ liệu không đạt.
|
|
15
|
+
ai-tool-chua-co-trong-danh-muc denied - - Muốn dùng công cụ mới: gửi đề nghị cho lead, ATTT đánh giá điều khoản dữ liệu rồi bổ sung vào danh mục này.
|
package/rules/gate.rules
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Rule của Cổng kiểm soát ATBMTT (VNPTNAN_GATE). Sửa file này phải qua merge request có ATTT duyệt.
|
|
2
|
+
#
|
|
3
|
+
# Mỗi dòng, ngăn bằng TAB: id level kind regex message
|
|
4
|
+
# level: block (từ chối commit/push), warn (cho qua, ghi log)
|
|
5
|
+
# kind:
|
|
6
|
+
# line regex so với từng DÒNG ĐƯỢC THÊM trong diff (hoặc mọi dòng khi quét cả cây)
|
|
7
|
+
# path regex so với đường dẫn file được thêm/sửa
|
|
8
|
+
# count regex field là "N|regex": file có từ N dòng khớp trở lên thì vi phạm (phát hiện dump dữ liệu)
|
|
9
|
+
# size regex field là "BYTES|regex": file khớp regex và lớn hơn BYTES thì vi phạm
|
|
10
|
+
# allow regex so với dòng nội dung; dòng khớp được bỏ qua mọi rule kind=line (giá trị mẫu, placeholder)
|
|
11
|
+
# exempt regex so với đường dẫn; file khớp được bỏ qua mọi rule kind=path
|
|
12
|
+
# Regex: không phân biệt hoa thường, cú pháp POSIX ERE (grep -E). Không dùng \d \w \s \b.
|
|
13
|
+
# Mọi id bắt đầu bằng "g-" để không trùng id của VNPTNAN_HARNESS (company.rules).
|
|
14
|
+
# Các dòng @tên là văn bản engine dùng khi trả lời.
|
|
15
|
+
@block-suffix Commit/push bị từ chối. Gỡ nội dung vi phạm khỏi thay đổi (hoặc khai ngoại lệ trong .vnptnan-gate/allow.rules qua merge request có ATTT duyệt). Không dùng --no-verify.
|
|
16
|
+
@warn-suffix Chỉ cảnh báo, đã ghi log. Hãy kiểm tra lại trước khi mở merge request.
|
|
17
|
+
@audit-suffix Chế độ thí điểm (audit): vi phạm mức block chỉ được ghi log, chưa từ chối.
|
|
18
|
+
|
|
19
|
+
# ===== 1. Secret và thông tin xác thực (block) =====
|
|
20
|
+
g-secret-private-key block line -----BEGIN ([A-Z]+ )?PRIVATE KEY----- Khoá bí mật dạng PEM.
|
|
21
|
+
g-secret-aws block line (^|[^A-Z0-9])(AKIA|ASIA)[0-9A-Z]{16}([^A-Z0-9]|$) AWS access key.
|
|
22
|
+
g-secret-github block line gh[pousr]_[A-Za-z0-9]{36,} GitHub token.
|
|
23
|
+
g-secret-gitlab block line glpat-[A-Za-z0-9_-]{20,} GitLab personal access token.
|
|
24
|
+
g-secret-anthropic block line sk-ant-[A-Za-z0-9_-]{20,} API key Anthropic (Claude).
|
|
25
|
+
g-secret-openai block line sk-(proj-)?[A-Za-z0-9_-]{20,}T3BlbkFJ[A-Za-z0-9_-]{20,} API key OpenAI.
|
|
26
|
+
g-secret-google block line AIza[0-9A-Za-z_-]{35} API key Google.
|
|
27
|
+
g-secret-slack block line xox[baprs]-[0-9A-Za-z-]{10,} Slack token.
|
|
28
|
+
g-secret-telegram block line [0-9]{8,10}:AA[0-9A-Za-z_-]{33} Telegram bot token.
|
|
29
|
+
g-secret-jwt block line eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,} JSON Web Token thật.
|
|
30
|
+
g-secret-url-cred block line [a-z][a-z0-9+.-]*://[^/:@ "']+:[^@/ "']{3,}@[a-z0-9.-] Mật khẩu nhúng trong URL (user:pass@host).
|
|
31
|
+
g-secret-connstring block line (data source|server|host|user id|uid)[ ]*=[^;]*;[^#]*(password|pwd)[ ]*=[ ]*[^;"' ]{4,} Chuỗi kết nối database có mật khẩu.
|
|
32
|
+
g-secret-oracle-ezconnect block line (^|[^a-z0-9_/])[a-z][a-z0-9_$]*/[^@/ \"']{4,}@(([a-z0-9-]+\.)+[a-z]{2,}|[0-9]{1,3}(\.[0-9]{1,3}){3}|[a-z0-9_.-]+:[0-9]{2,5})(:[0-9]+)?(/[a-z0-9_.]+)?([^a-z0-9_.]|$)|(sqlplus|sqlldr|rman|expdp|impdp)[^\"']* [a-z][a-z0-9_$]*/[^@/ \"']{4,}@[a-z0-9_]+ Chuỗi user/mật_khẩu@host/service của Oracle.
|
|
33
|
+
g-secret-generic-key block line (api[_-]?key|secret[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|private[_-]?key|refresh[_-]?token)["']?[ ]*[:=][ ]*["'][A-Za-z0-9/+_=.-]{16,}["'] Khoá/token gán cứng trong mã.
|
|
34
|
+
g-secret-password block line (password|passwd|pwd|mat[_-]?khau|matkhau)["']?[ ]*[:=][ ]*["'][^"']{6,}["'] Mật khẩu gán cứng trong mã.
|
|
35
|
+
g-secret-basic-auth block line authorization["']?\]?[ ]*[:=][ ]*["']?basic [A-Za-z0-9+/=]{16,} Header Basic Auth chứa thông tin xác thực.
|
|
36
|
+
g-secret-bearer block line authorization["']?\]?[ ]*[:=][ ]*["']?bearer [A-Za-z0-9._-]{20,} Header Bearer token thật.
|
|
37
|
+
|
|
38
|
+
# ===== 2. Dữ liệu cá nhân và dữ liệu khách hàng (Luật BVDLCN 91/2025/QH15) =====
|
|
39
|
+
g-pii-cccd block line (cccd|cmnd|can cuoc|căn cước|so dinh danh|số định danh|citizen[_ ]?id|national[_ ]?id)[^0-9]{0,40}0[0-9]{11}([^0-9]|$) Số CCCD/định danh cá nhân thật.
|
|
40
|
+
g-pii-phone-bulk block count 20|(^|[^0-9])(0|\+84)(3|5|7|8|9)[0-9]{8}([^0-9]|$) File chứa hàng loạt số điện thoại: dấu hiệu dump dữ liệu khách hàng.
|
|
41
|
+
g-pii-email-bulk warn count 50|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,} File chứa hàng loạt địa chỉ email.
|
|
42
|
+
g-pii-cccd-bulk block count 10|(^|[^0-9])0[0-9]{11}([^0-9]|$) File chứa hàng loạt số 12 chữ số: dấu hiệu dump CCCD.
|
|
43
|
+
g-data-dump warn size 1048576|\.(sql|dmp|dump|bak|csv|tsv|xlsx?|json)$ File dữ liệu lớn hơn 1 MB: kiểm tra có phải dữ liệu thật của khách hàng không.
|
|
44
|
+
|
|
45
|
+
# ===== 3. Thông tin hạ tầng nội bộ (warn) =====
|
|
46
|
+
g-internal-ip warn line (^|[^0-9.])(10\.[0-9]{1,3}|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.[0-9]{1,3}\.[0-9]{1,3}([^0-9.]|$) Địa chỉ IP mạng nội bộ trong mã nguồn.
|
|
47
|
+
g-internal-host warn line [a-z0-9-]+\.(vnpt\.vn|vnpt\.local|vnptna\.local|nghean\.local|corp\.local) Tên máy chủ nội bộ trong mã nguồn.
|
|
48
|
+
|
|
49
|
+
# ===== 4. File không được đưa vào repo (path) =====
|
|
50
|
+
g-path-env block path (^|/)\.env(\.[^/]+)?$ File .env chứa secret.
|
|
51
|
+
g-path-key block path \.(pem|key|pfx|p12|jks|keystore|ppk|asc|gpg|kdbx)$ File khoá bí mật.
|
|
52
|
+
g-path-cloud-cred block path (^|/)(\.aws/credentials|\.git-credentials|\.docker/config\.json|\.kube/config|\.npmrc|\.pypirc|\.netrc|_netrc)$ File credential của công cụ.
|
|
53
|
+
g-path-appsettings block path (^|/)appsettings\.(production|staging|prod)[^/]*\.json$ Cấu hình môi trường thật có thể chứa secret.
|
|
54
|
+
g-path-oracle-wallet block path (^|/)(cwallet\.sso|ewallet\.p12|ewallet\.pem)$ Oracle wallet.
|
|
55
|
+
g-path-oracle-net warn path (^|/)(tnsnames\.ora|sqlnet\.ora|ldap\.ora)$ Cấu hình mạng Oracle lộ địa chỉ máy chủ.
|
|
56
|
+
g-path-ai-config block path (^|/)(\.claude/settings\.local\.json|\.claude\.json|\.codex/auth\.json|\.codex/config\.toml|\.gemini/oauth_creds\.json|\.mcp\.json|\.cursor/mcp\.json)$ Cấu hình cục bộ của công cụ AI thường chứa token.
|
|
57
|
+
g-path-ai-session block path (^|/)(\.claude/projects/|\.claude/history\.jsonl|\.codex/sessions/|\.codex/history\.jsonl|\.vnptnanskill/) Bản ghi phiên làm việc với AI chứa toàn bộ ngữ cảnh, không đưa lên repo.
|
|
58
|
+
g-path-db-file warn path \.(dmp|bak|mdf|ldf|sqlite|db)$ File database: kiểm tra có dữ liệu thật không.
|
|
59
|
+
g-exempt-sample block exempt \.(example|sample|template|dist)(\.[a-z]+)?$ File mẫu, không chứa secret thật.
|
|
60
|
+
|
|
61
|
+
# ===== 5. Dấu vết mã do AI sinh ra chưa được rà soát (warn) =====
|
|
62
|
+
g-ai-placeholder warn line (\.\.\. ?(existing|rest of( the)?|remaining|previous) code|(//|#|<!--) ?\.\.\. ?(existing|rest|unchanged)|as an ai (language )?model|i cannot (help|assist) with) AI để sót đoạn placeholder trong mã.
|
|
63
|
+
g-ai-todo warn line (todo|fixme)[: ]+.*(ai[ -]generated|generated by (ai|claude|codex|copilot|gemini)|verify this) Mã AI sinh ra có ghi chú chưa được kiểm tra.
|
|
64
|
+
|
|
65
|
+
# ===== 6. Mẫu mã không an toàn phổ biến khi AI sinh mã (warn, SAST nhẹ) =====
|
|
66
|
+
g-sast-tls-off warn line (ServerCertificateValidationCallback[ ]*=.*true|TrustServerCertificate[ ]*=[ ]*true|rejectUnauthorized[ ]*:[ ]*false|verify[ ]*=[ ]*false|NODE_TLS_REJECT_UNAUTHORIZED[ ]*=[ ]*["']?0) Tắt kiểm tra chứng thư TLS.
|
|
67
|
+
g-sast-cors-any warn line (AllowAnyOrigin\(\)|Access-Control-Allow-Origin["' ]*[:,][ ]*["']\*) CORS mở cho mọi origin.
|
|
68
|
+
g-sast-sql-concat warn line (ExecuteSqlRaw|FromSqlRaw|SqlCommand|OracleCommand|\.query)\([^)]*(\+|\$"|string\.Format) Câu SQL ghép chuỗi: nguy cơ SQL injection.
|
|
69
|
+
g-sast-weak-hash warn line (MD5|SHA1)\.Create\(|createHash\(["'](md5|sha1)["']\) Thuật toán băm yếu cho mục đích bảo mật.
|
|
70
|
+
g-sast-eval warn line (^|[^a-z_.])(eval|new Function)\(|dangerouslySetInnerHTML|Process\.Start\([^)]*\+ Thực thi mã/lệnh động từ chuỗi.
|
|
71
|
+
g-sast-destructive-code warn line (EnsureDeleted(Async)?\(|Execute(Sql|SqlRaw|SqlInterpolated)[A-Za-z]*\([^)]*(drop|truncate) ) Mã xoá dữ liệu khi chạy (VNPTNAN_HARNESS đã hỏi lúc AI ghi; cổng ghi vết lần nữa trước khi lên repo).
|
|
72
|
+
|
|
73
|
+
# ===== 7. Giá trị mẫu được bỏ qua (allow) =====
|
|
74
|
+
g-allow-placeholder warn allow (changeme|change_me|your[_-]?(api[_-]?key|token|password|secret)|<[a-z_ -]+>|\$\{[a-z_.:-]+\}|\{\{[a-z_. -]+\}\}|%[A-Z_]+%|xxxx|\*\*\*\*|placeholder|example\.com|dummy|khong-phai-that|(^|["'=: ])(password123|123456|secret123|p@ssw0rd|admin123)(["' ]|$)) Giá trị mẫu, không phải secret thật.
|
|
75
|
+
# Ngoại lệ tại chỗ: thêm "gate-allow:<id-rule> <lý do>" vào chính dòng đó (engine xử lý, chỉ bỏ qua đúng rule đó, vẫn ghi log).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Rule về thành phần bên thứ ba (dependency) và giấy phép. Sửa qua merge request có ATTT và Pháp chế duyệt.
|
|
2
|
+
#
|
|
3
|
+
# Mỗi dòng, ngăn bằng TAB: type level regex message
|
|
4
|
+
# type:
|
|
5
|
+
# deny-license regex so với tên giấy phép của package (từ package.json hoặc .nuspec)
|
|
6
|
+
# deny-package regex so với tên package (npm hoặc NuGet), không phân biệt hoa thường
|
|
7
|
+
# allow-registry regex so với URL registry cho phép (npm registry / NuGet source); nếu có dòng này, URL khác sẽ warn
|
|
8
|
+
# level: block, warn
|
|
9
|
+
#
|
|
10
|
+
# Giấy phép copyleft mạnh không dùng trong sản phẩm phân phối cho khách hàng (Pháp chế rà theo P0.11 của Harness).
|
|
11
|
+
deny-license block ^(AGPL|GPL-3|GPL-2|SSPL|EUPL|CC-BY-NC|BUSL) Giấy phép copyleft/giới hạn thương mại, cần Pháp chế duyệt trước khi dùng.
|
|
12
|
+
deny-license warn ^(LGPL|MPL|CDDL|EPL|OSL) Giấy phép copyleft yếu, cần ghi nhận và tuân thủ điều kiện.
|
|
13
|
+
deny-license warn ^(UNLICENSED|UNKNOWN|SEE LICENSE|NONE)?$ Package không khai giấy phép, không được dùng khi chưa rõ.
|
|
14
|
+
# Package bị gỡ/độc hại hoặc tên hay bị AI bịa (slopsquatting). Bổ sung khi ATTT có thông tin.
|
|
15
|
+
deny-package block ^(event-stream@3\.3\.6|ua-parser-js@0\.7\.29|colors@1\.4\.1|faker@6\.6\.6|node-ipc@(10\.1\.[12]|9\.2\.2))$ Package có lịch sử bị cài mã độc.
|
|
16
|
+
deny-package warn ^(request|node-sass|moment|tslint|protractor|bower|gulp-util)$ Package đã ngừng bảo trì (deprecated).
|
|
17
|
+
# Registry cho phép. Khi có registry nội bộ, thêm dòng và chuyển mức sang block.
|
|
18
|
+
allow-registry warn ^https://(registry\.npmjs\.org|api\.nuget\.org)/ Registry chính thức.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Server hook pre-receive cho GitLab tự host (mọi bậc, kể cả Free): lớp kiểm soát không phụ thuộc máy dev.
|
|
3
|
+
# Cài toàn cục: copy thư mục VNPTNAN_GATE lên máy chủ (ví dụ /opt/vnptnan-gate), rồi
|
|
4
|
+
# ln -s /opt/vnptnan-gate/server/pre-receive /var/opt/gitlab/gitaly/custom_hooks/pre-receive.d/10-vnptnan-gate
|
|
5
|
+
# Xem installer/install-server.sh. GitLab chỉ hiện ra cho người đẩy những dòng bắt đầu bằng "GL-HOOK-ERR:".
|
|
6
|
+
# stdin: <old> <new> <ref> mỗi dòng. Biến có sẵn: GL_ID GL_USERNAME GL_PROJECT_PATH GL_PROTOCOL GL_REPOSITORY.
|
|
7
|
+
root=${VNPTNAN_GATE_HOME:-$(cd "$(dirname "$(readlink -f "$0")")/.." && pwd)}
|
|
8
|
+
export GATE_SERVER=1
|
|
9
|
+
export GATE_LOG=${GATE_LOG:-/var/log/vnptnan-gate/gate.log}
|
|
10
|
+
# Trên server không có node_modules hay cache NuGet: chỉ quét nội dung.
|
|
11
|
+
export GATE_DEPS=off
|
|
12
|
+
# Bỏ qua kiểm tra khi push được GitLab tạo (web UI merge, revert) nếu muốn: GL_PROTOCOL=web. Mặc định vẫn quét.
|
|
13
|
+
exec bash "$root/engine/gate-scan.sh" receive
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiểm tra cú pháp các file rule: đúng số cột, mức và loại hợp lệ, regex biên dịch được bằng grep -E, id không trùng và đều bắt đầu bằng g-.
|
|
3
|
+
set -u
|
|
4
|
+
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
5
|
+
err=0
|
|
6
|
+
check_regex() { printf 'x' | grep -qiE -- "$1" 2>/dev/null; [ $? -le 1 ]; }
|
|
7
|
+
|
|
8
|
+
ids=()
|
|
9
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
10
|
+
line=${line%$'\r'}
|
|
11
|
+
[ -z "$line" ] && continue
|
|
12
|
+
case "$line" in '#'*|'@'*) continue ;; esac
|
|
13
|
+
IFS=$'\t' read -r id level kind re msg <<< "$line"
|
|
14
|
+
[ "$(printf '%s' "$line" | awk -F'\t' '{print NF}')" = 5 ] || { echo "gate.rules: sai số cột: $line"; err=1; }
|
|
15
|
+
case "$id" in g-*) ;; *) echo "gate.rules: id phải bắt đầu bằng g- (tránh trùng VNPTNAN_HARNESS): $id"; err=1 ;; esac
|
|
16
|
+
for x in "${ids[@]:-}"; do [ "$x" = "$id" ] && { echo "gate.rules: id trùng: $id"; err=1; }; done
|
|
17
|
+
ids+=("$id")
|
|
18
|
+
case "$level" in block|warn) ;; *) echo "gate.rules: mức sai ở $id: $level"; err=1 ;; esac
|
|
19
|
+
case "$kind" in
|
|
20
|
+
line|path|allow|exempt) check_regex "$re" || { echo "gate.rules: regex không hợp lệ ở $id"; err=1; } ;;
|
|
21
|
+
count|size) case "$re" in [0-9]*'|'*) check_regex "${re#*|}" || { echo "gate.rules: regex không hợp lệ ở $id"; err=1; } ;; *) echo "gate.rules: $kind cần dạng N|regex ở $id"; err=1 ;; esac ;;
|
|
22
|
+
*) echo "gate.rules: loại sai ở $id: $kind"; err=1 ;;
|
|
23
|
+
esac
|
|
24
|
+
printf '%s' "$re" | grep -qE '\\[dwsb]|\(\?' && { echo "gate.rules: $id dùng \\d \\w \\s \\b hoặc (?...) không có trong POSIX ERE"; err=1; }
|
|
25
|
+
done < "$ROOT/rules/gate.rules"
|
|
26
|
+
|
|
27
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
28
|
+
line=${line%$'\r'}
|
|
29
|
+
[ -z "$line" ] && continue
|
|
30
|
+
case "$line" in '#'*) continue ;; esac
|
|
31
|
+
IFS=$'\t' read -r t l re msg <<< "$line"
|
|
32
|
+
case "$t" in deny-license|deny-package|allow-registry) ;; *) echo "packages.rules: loại sai: $t"; err=1 ;; esac
|
|
33
|
+
case "$l" in block|warn) ;; *) echo "packages.rules: mức sai: $l"; err=1 ;; esac
|
|
34
|
+
check_regex "$re" || { echo "packages.rules: regex không hợp lệ: $re"; err=1; }
|
|
35
|
+
done < "$ROOT/rules/packages.rules"
|
|
36
|
+
|
|
37
|
+
[ "$err" = 0 ] && echo "rules ok: ${#ids[@]} rule" || exit 1
|