Conversation
KakaoTalk audit produced 103 code findings but only 54 unique
(rule, class) keys — 49 of 103 were the same rule firing repeatedly
inside the same class (e.g. com.caverock.androidsvg.i fired CODE-001
12 times). Operators scrolled past identical cards.
This commit collapses findings sharing (rule_id, class_fqn, severity)
into one representative + a list of additional occurrences:
CodeFinding gains:
occurrences: list[CodeOccurrence] = []
occurrence_count property (1 + len(occurrences))
CodeOccurrence (new dataclass) carries:
line_no, line_text, file (only when different from primary),
evidence_tier (inherits the parent finding's tier by default)
dedup_findings_by_class(findings) helper applies the merge — used
by audit_code() and audit_smali() at their respective return paths.
Severity is part of the key so CODE-002's medium
setJavaScriptEnabled(true) and high addJavascriptInterface stay
as two findings (operators triaging by severity would lose the
high signal otherwise).
JSON round-trip: occurrences serialize only when non-empty; default
empty list keeps older payloads compact and forward-compatible.
KakaoTalk effect (back-of-envelope from existing partial scan):
103 findings → 54 representatives (47% compression)
Same evidence retained as occurrences; nothing dropped.
Tests +14:
- dedup empty / distinct rules / distinct classes / same class collapse
- severity-aware key prevents merging different severities
- exact-line duplicate folded down to representative only
- class_fqn=="" falls back to file as grouping anchor
- evidence_tier preserved in CodeOccurrence
- CodeFinding to/from_dict round-trips occurrences
- audit_code() end-to-end dedup via real source files
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
KakaoTalk's RecentExcludeIntentFilterActivity carries 43 intent-filter
actions and the audit emitted 43 separate adb PoCArtifacts, each
running one ``am start -a <action>`` command. Operators saw the same
template repeated 43 times, with only the action string changing.
This commit consolidates per-component: one PoCArtifact per exported
component whose commands list runs every action sequentially. The
artifact title is "<type> '<class>' 호출 — N actions" when there are
multiple actions, and the single-action case keeps the old short title.
Effect on KakaoTalk regression (back-of-envelope):
- 190 PoCs → ~50 PoCs (single-PoC-per-component + Frida observer +
deeplinks unchanged)
- The most repetitive case (43 actions in one component) becomes
one 45-line .sh
The Frida observer artifact and deeplink PoCs are unchanged — those
already operate at component scope. Only the per-action adb fanout
collapses.
Tests +1, modified existing test to reflect single-PoC semantics:
- test_actions_grouped_into_single_artifact_per_component
- test_single_action_no_action_count_suffix (clean title case)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
KakaoTalk emitted 190 PoCArtifacts where many shared the same shell /
adb template — only the component class FQN or deeplink URI differed.
Operators got identical .sh scripts with just one varying token,
making the bundle exhausting to scan.
This commit adds template-level dedup on top of the per-component
collapse from Phase 11-2:
PoCArtifact gains:
applies_to: list[str] # other targets the same template covers
dedup_pocs_by_template(artifacts) helper folds artifacts sharing
(rule_id, kind, severity, command-template) into one representative
+ applies_to list of additional targets. generate_pocs() runs the
dedup automatically before returning.
Template signature normalizes:
- com.* class FQNs and dotted hostnames → <T>
- kakao{type}:// and http(s):// URIs → <T>
- title strings get the same substitution
So "외부 노출 액티비티 'com.demo.A' 호출" + commands "am start -n A"
matches the same shape as ".B" / "am start -n B".
Severity and kind are part of the key — high vs medium templates stay
separate (operators triaging by severity must not lose the high
signal). Different transports (adb / frida) also remain separate.
Effect on KakaoTalk regression (with P11-2 already applied):
~50 PoCs → ~25-30 PoCs after template fold; each surviving PoC now
carries applies_to with the merged component FQNs so the operator
sees "이 .sh는 다음 N개 컴포넌트에 적용 가능" at-a-glance.
Tests +9:
- empty input / unique passthrough / same-shape different-component
- 3 → 1 with applies_to listing both extras
- severity and kind respected (no cross-merge)
- deeplink URI host normalization
- applies_to JSON round-trip + omit when empty
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renders the Phase 11-1 / 11-3 dedup outputs so the HTML report shows
the compression the data layer already achieves:
CodeFinding cards:
- "×N건" sev-chip badge in the card header when occurrence_count > 1
- "tier: smali" badge when evidence_tier != "java" (java tier omits)
- Collapsible <details> with "동일 클래스 내 추가 단서 N건 펼치기"
listing every occurrence (line_no, line_text, file when different,
evidence_tier label when it diverges from the parent finding)
- Badge / details omitted entirely when count == 1 and occurrences
is empty — single findings render identically to pre-Phase-11
PoC <details> entries:
- "+N 적용" chip in summary when applies_to has entries
- Inline <ul> under "다음 컴포넌트에도 동일 템플릿 적용 가능"
so the operator can copy alternative targets without leaving the
card
- Chip / list both omitted when applies_to is empty
Pre-existing severity / MASVS / partial banners are untouched; the
new badges sit alongside them in the card header.
Tests +4:
- code finding occurrence badge + collapsible details + smali label
- no badge when single occurrence
- tier: smali label render for smali-tier findings
- PoC applies_to chip + body list render via real builder output
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
merge_code_reports previously dropped the smali finding entirely when
the .java tier had already reported the same (rule, class). That was
correct for the *card count* but wasted evidence: smali often catches
extra lines that jadx couldn't decompile inside the same class.
This commit folds the smali side into the java representative's
occurrences instead of discarding it:
- Merge key tightened to (rule_id, class_or_file, severity) so
different severities of the same rule (CODE-002 medium vs high)
stay as separate cards — matches the dedup_findings_by_class key
- On overlap, smali's primary (line_no, line_text, file) folds in as
a CodeOccurrence with evidence_tier="smali"
- smali's own occurrences (from smali-tier dedup) also fold in, each
labelled "smali"
- File path in the occurrence is omitted when it matches the java
rep's file (avoids redundant "x.java" everywhere)
Effect on KakaoTalk-class APKs: previously when both tiers hit the
same class, the smali findings disappeared from the report; now they
appear as additional evidence on the java card so operators see the
full picture without inflating the card count.
Tests +2 (1 existing test rewritten):
- existing "java wins on overlap" updated to assert the smali fold
- smali's own occurrences (already-grouped smali bundle) also fold
- different severity on same class keeps two separate cards
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Lead bullets: explicit "PoC 자동 생성 + dedup" with the KakaoTalk 190→17 (-91%) measurement, "결과 정규화" callout for occurrence grouping. HTML bullet mentions the new occurrence expand + chips. - Project Layout test count bumped 834 → 864. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
KakaoTalk audit showed three duplication patterns:
Phase 11 normalises the data layer + HTML so the report shows what
the analyzer actually found, compactly.
cbc4c94CodeFinding.occurrences — same (rule, class, severity)collapses to representative + list of additional line refs
cb38329MANIFEST-004 single-PoC-per-component — N actionsbecome one .sh trying each action sequentially (was: N separate .sh)
214a0d4PoC template dedup — same (rule, kind, severity,normalized template) merges;
applies_tocarries other componentsd4e3cf2HTML grouping UI — "×N건" badge + collapsibleoccurrence list + "+N 적용" chip + applies_to inline list
b1aecc9java/smali tier overlap fold — smali primary +occurrences fold into java rep's occurrences as additional evidence
(was: dropped silently)
KakaoTalk before/after:
Test plan
4 P11-4, 3 P11-5)
output — numbers above are real (not projected)
PoCArtifact.applies_to) — both default to empty list and omit
from to_dict when unused, so older payloads load forward-compat
drop without losing findings (operator manual verification)
Codex review handoff
outputs/intent.md— per-unit intent / risk / verification checklist.🤖 Generated with Claude Code