@yottameta/yotta-intel 0.2.0 → 0.2.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/CHANGELOG.md +10 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/SKILL.md +1 -1
- package/install.sh +24 -5
- package/package.json +1 -1
- package/references/defang-rules.md +1 -1
- package/references/ioc-spec.md +1 -1
- package/references/stix-lite-spec.md +1 -1
- package/scripts/test_yotta_intel.py +1 -1
- package/scripts/yotta_intel.py +19 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## v0.2.1 (2026-09-25)
|
|
4
|
+
|
|
5
|
+
维护性发布:安装器加固 + README 锁定版本。
|
|
6
|
+
|
|
7
|
+
- 安装器:拒绝对符号链接目标写入、目标不是目录时拒绝、不做整目录删除。
|
|
8
|
+
- README(中英):安装命令改为锁定版本写法(去掉 `@版本` 即跟随最新)。
|
|
9
|
+
- 输出示例与 references 头部版本号同步 0.2.1。
|
|
10
|
+
- 修复:IPv4 前导零写法(`010.000.000.001`)归一为 `10.0.0.1` —— Python 3.9.5 起
|
|
11
|
+
`ipaddress.IPv4Address` 拒绝前导零八位组,旧引擎会静默丢掉该地址;`999.1.1.1` 仍判非法。
|
|
12
|
+
|
|
3
13
|
## v0.2.0 (2026-09-09)
|
|
4
14
|
|
|
5
15
|
- 评测完善批 2:新增 references/faq.md(12 条常见问题 + 速查索引 + 安装排障);SKILL.md 增加 FAQ 速查节。
|
package/README.md
CHANGED
|
@@ -91,7 +91,7 @@ python3 scripts/yotta_intel.py refang --path safe.txt
|
|
|
91
91
|
Sample text output:
|
|
92
92
|
|
|
93
93
|
```
|
|
94
|
-
元情 yotta-intel v0.2.
|
|
94
|
+
元情 yotta-intel v0.2.1 —— IOC 提取结果
|
|
95
95
|
共发现 2 个 IOC:
|
|
96
96
|
|
|
97
97
|
■ IPv4 地址(ipv4)
|
|
@@ -108,8 +108,8 @@ Pick any of the four methods below; the order is the recommended priority. Skill
|
|
|
108
108
|
|
|
109
109
|
```text
|
|
110
110
|
# Optional China mirror: npm config set registry https://registry.npmmirror.com
|
|
111
|
-
npx -y @yottameta/yotta-intel --agent <agent-name> # install to the agent's default user-level skills dir
|
|
112
|
-
npx -y @yottameta/yotta-intel --dir <your-skills-dir> # point to the skills dir itself (e.g. ~/.codex/skills)
|
|
111
|
+
npx -y @yottameta/yotta-intel@0.2.1 --agent <agent-name> # install to the agent's default user-level skills dir
|
|
112
|
+
npx -y @yottameta/yotta-intel@0.2.1 --dir <your-skills-dir> # point to the skills dir itself (e.g. ~/.codex/skills)
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
- `--agent <name>` installs to that agent's default user-level directory; `--list` shows each agent's default directory.
|
package/README.zh-CN.md
CHANGED
|
@@ -99,7 +99,7 @@ python3 scripts/yotta_intel.py refang --path safe.txt
|
|
|
99
99
|
输出示例(text):
|
|
100
100
|
|
|
101
101
|
```
|
|
102
|
-
元情 yotta-intel v0.2.
|
|
102
|
+
元情 yotta-intel v0.2.1 —— IOC 提取结果
|
|
103
103
|
共发现 2 个 IOC:
|
|
104
104
|
|
|
105
105
|
■ IPv4 地址(ipv4)
|
|
@@ -116,8 +116,8 @@ python3 scripts/yotta_intel.py refang --path safe.txt
|
|
|
116
116
|
|
|
117
117
|
```text
|
|
118
118
|
# 可选国内加速:npm config set registry https://registry.npmmirror.com
|
|
119
|
-
npx -y @yottameta/yotta-intel --agent <智能体名称> # 装到指定智能体默认用户级技能目录
|
|
120
|
-
npx -y @yottameta/yotta-intel --dir <智能体的技能目录> # 指到技能目录本身(如 ~/.codex/skills)
|
|
119
|
+
npx -y @yottameta/yotta-intel@0.2.1 --agent <智能体名称> # 装到指定智能体默认用户级技能目录
|
|
120
|
+
npx -y @yottameta/yotta-intel@0.2.1 --dir <智能体的技能目录> # 指到技能目录本身(如 ~/.codex/skills)
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
- `--agent <name>` 自动装到该智能体默认用户级目录;`--list` 可查看各智能体默认目录。
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-intel
|
|
3
|
-
version: 0.2.
|
|
3
|
+
version: 0.2.1
|
|
4
4
|
description: 元情 —— 跨智能体的威胁情报 IOC 提取与规范化技能:零依赖自研从文本 / 日志 / 报告中提取 IP(IPv4/IPv6)、域名、URL、邮箱、哈希(MD5/SHA1/SHA256/SHA512)与 CVE 编号,识别并还原 defang 写法,去重、归一化后输出 CSV / JSON / STIX-lite。触发:用户给出含可疑 IP / 域名 / URL / 哈希的威胁情报文本、恶意样本分析报告、钓鱼邮件或日志,要提取 IOC、规范化、去重、转格式、共享情报时。边界:纯本地离线提取与规范化;不联网查证、不下载样本、不主动扫描任何系统;仅用于已获授权 / 自有资产 / 教学环境的安全分析。
|
|
5
5
|
license: MIT
|
|
6
6
|
---
|
package/install.sh
CHANGED
|
@@ -61,10 +61,29 @@ resolve_user() {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
install_to() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
local base="$1"
|
|
65
|
+
local dest
|
|
66
|
+
case "$base" in
|
|
67
|
+
""|"/") echo "安装失败:拒绝不安全的目标目录:'$base'" >&2; return 1 ;;
|
|
68
|
+
esac
|
|
69
|
+
if [ -L "$base" ]; then
|
|
70
|
+
echo "安装失败:目标目录是符号链接,拒绝跟随:$base" >&2; return 1
|
|
71
|
+
fi
|
|
72
|
+
mkdir -p "$base"
|
|
73
|
+
dest="$base/$SKILL_NAME"
|
|
74
|
+
if [ -L "$dest" ]; then
|
|
75
|
+
echo "安装失败:技能目录是符号链接,拒绝跟随:$dest" >&2; return 1
|
|
76
|
+
fi
|
|
77
|
+
if [ -e "$dest" ] && [ ! -d "$dest" ]; then
|
|
78
|
+
echo "安装失败:技能路径已存在且不是目录:$dest" >&2; return 1
|
|
79
|
+
fi
|
|
80
|
+
mkdir -p "$dest"
|
|
81
|
+
cp -RP "$SOURCE_DIR/." "$dest/"
|
|
82
|
+
# 只清理副本内部的开发残留(固定子路径),不做整目录删除、不跟随符号链接
|
|
83
|
+
if [ -d "$dest/.git" ] && [ ! -L "$dest/.git" ]; then rm -rf "$dest/.git"; fi
|
|
84
|
+
find "$dest" -type d -name '__pycache__' -prune -exec rm -rf {} + 2>/dev/null || true
|
|
85
|
+
find "$dest" -type f -name '*.pyc' -delete 2>/dev/null || true
|
|
86
|
+
echo "installed -> $dest"
|
|
68
87
|
}
|
|
69
88
|
|
|
70
89
|
list() {
|
|
@@ -129,4 +148,4 @@ main() {
|
|
|
129
148
|
fi
|
|
130
149
|
}
|
|
131
150
|
|
|
132
|
-
main "$@"
|
|
151
|
+
main "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-intel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Yuanqing — a zero-dependency threat-intel IOC extraction & normalization engine for AI agents: extracts IP (IPv4/IPv6), domains, URLs, emails, hashes (MD5/SHA1/SHA256/SHA512) and CVE IDs from threat reports, phishing emails and logs; recognizes and reverses defanged forms (hxxp / [.] / (.) / [dot] / [:] / [@]); deduplicates, normalizes (IDN punycode, default-port stripping) and outputs CSV / JSON / STIX-lite (STIX 2.1 Bundle) with the pure Python 3.8+ standard library. Triggers when the user provides text containing suspicious IPs / domains / URLs / hashes and needs IOC extraction, normalization, dedup, format conversion, or safe sharing. Boundaries: fully local and offline; no reputation lookups, no sample downloads, no proactive scanning; authorized / own-asset / educational use only.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
package/references/ioc-spec.md
CHANGED
|
@@ -488,7 +488,7 @@ class TestCLI(unittest.TestCase):
|
|
|
488
488
|
def test_cli_version(self):
|
|
489
489
|
r = run_cli("--version")
|
|
490
490
|
self.assertEqual(r.returncode, 0)
|
|
491
|
-
self.assertIn("0.2.
|
|
491
|
+
self.assertIn("0.2.1", r.stdout)
|
|
492
492
|
|
|
493
493
|
def test_cli_unknown_type_exit4(self):
|
|
494
494
|
r = run_cli("extract", "--stdin", "--types", "bogus", stdin="1.2.3.4")
|
package/scripts/yotta_intel.py
CHANGED
|
@@ -52,7 +52,7 @@ try:
|
|
|
52
52
|
except Exception:
|
|
53
53
|
pass
|
|
54
54
|
|
|
55
|
-
VERSION = "0.2.
|
|
55
|
+
VERSION = "0.2.1"
|
|
56
56
|
TOOL = "yotta-intel"
|
|
57
57
|
TOOL_CN = "元情"
|
|
58
58
|
|
|
@@ -188,6 +188,23 @@ URL_RE = re.compile(r"(?i)(?:(?:https?|ftp)://)[^\s<>\"',。!?;:、(
|
|
|
188
188
|
EMAIL_RE = re.compile(r"(?i)[a-z0-9._%+\-]+@[a-z0-9\-]+(?:\.[a-z0-9\-]+)+")
|
|
189
189
|
DOMAIN_RE = re.compile(r"(?<![\w@.])(?:[\w\-]{1,63}\.)+[\w\-]{2,63}(?![\-\w])")
|
|
190
190
|
IPV4_RE = re.compile(r"(?<!\d)(?:\d{1,3}\.){3}\d{1,3}(?!\d)")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def normalize_ipv4_octets(raw):
|
|
194
|
+
"""把前导零写法(010.000.000.001)归一为 10.0.0.1。
|
|
195
|
+
|
|
196
|
+
Python 3.9.5 起 ipaddress.IPv4Address 拒绝前导零八位组,旧版本接受;
|
|
197
|
+
这里先做十进制归一,保证跨版本行为一致(999.1.1.1 仍会被判非法)。
|
|
198
|
+
"""
|
|
199
|
+
parts = raw.split(".")
|
|
200
|
+
if len(parts) != 4:
|
|
201
|
+
return raw
|
|
202
|
+
out = []
|
|
203
|
+
for part in parts:
|
|
204
|
+
if not part.isdigit() or len(part) > 3:
|
|
205
|
+
return raw
|
|
206
|
+
out.append(str(int(part)))
|
|
207
|
+
return ".".join(out)
|
|
191
208
|
IPV6_TOKEN_RE = re.compile(r"(?i)(?<![\w:])(?:[0-9a-f:.]{2,45})(?![\w:])")
|
|
192
209
|
HASH_RE = re.compile(r"(?i)(?<![0-9a-f])[0-9a-f]{32,128}(?![0-9a-f])")
|
|
193
210
|
CVE_RE = re.compile(r"(?i)\bcve-\d{4}-\d{4,7}\b")
|
|
@@ -287,7 +304,7 @@ def find_iocs_in_line(line):
|
|
|
287
304
|
for m in IPV4_RE.finditer(line):
|
|
288
305
|
raw = m.group(0)
|
|
289
306
|
try:
|
|
290
|
-
ip = ipaddress.IPv4Address(raw)
|
|
307
|
+
ip = ipaddress.IPv4Address(normalize_ipv4_octets(raw))
|
|
291
308
|
except ValueError:
|
|
292
309
|
continue
|
|
293
310
|
found.append((m.start(), m.end(), "ipv4", str(ip)))
|