mirror of
https://github.com/lunchcat/sif.git
synced 2026-01-11 20:45:26 -08:00
Merge pull request #56 from 0x4bs3nt/feat/astro-framework-detection
feat(frameworks): add Astro framework detection
This commit is contained in:
@@ -424,6 +424,65 @@ func TestDetectFramework_Joomla(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectFramework_Astro(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html data-astro-transition="forward">
|
||||
<head>
|
||||
<meta name="generator" content="Astro v5.16.6">
|
||||
<link rel="stylesheet" href="/_astro/index.abc123.css">
|
||||
</head>
|
||||
<body>
|
||||
<astro-island data-astro-cid-xyz789 data-astro-source-file="src/components/Counter.astro">
|
||||
<div>Content</div>
|
||||
</astro-island>
|
||||
<nav>
|
||||
<a href="/about" data-astro-history="push">About</a>
|
||||
<a href="/external" data-astro-reload>External</a>
|
||||
</nav>
|
||||
<script src="/_astro/hoisted.def456.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("expected result, got nil")
|
||||
}
|
||||
if result.Name != "Astro" {
|
||||
t.Errorf("expected framework 'Astro', got '%s'", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractVersion_Astro(t *testing.T) {
|
||||
tests := []struct {
|
||||
body string
|
||||
expected string
|
||||
}{
|
||||
{`<meta name="generator" content="Astro v4.2.0">`, "4.2.0"},
|
||||
{`<meta name="generator" content="Astro 3.5.1">`, "3.5.1"},
|
||||
{"Astro 4.0.0", "4.0.0"},
|
||||
{"Astro/3.2.1", "3.2.1"},
|
||||
{`"astro": "^4.1.0"`, "4.1.0"},
|
||||
{`"astro": "~3.0.5"`, "3.0.5"},
|
||||
{"no version", "unknown"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := frameworks.ExtractVersionOptimized(tt.body, "Astro").Version
|
||||
if result != tt.expected {
|
||||
t.Errorf("ExtractVersionOptimized(%q, 'Astro') = %q, want %q", tt.body, result, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCVEEntry_Fields(t *testing.T) {
|
||||
entry := frameworks.CVEEntry{
|
||||
CVE: "CVE-2021-3129",
|
||||
@@ -452,7 +511,7 @@ func TestDetectorRegistry(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check that some expected detectors are registered
|
||||
expectedDetectors := []string{"Laravel", "Django", "React", "Vue.js", "Angular", "Next.js", "WordPress"}
|
||||
expectedDetectors := []string{"Laravel", "Django", "React", "Vue.js", "Angular", "Next.js", "WordPress", "Astro"}
|
||||
for _, name := range expectedDetectors {
|
||||
if _, ok := frameworks.GetDetector(name); !ok {
|
||||
t.Errorf("expected detector %q to be registered", name)
|
||||
|
||||
@@ -32,6 +32,7 @@ func init() {
|
||||
fw.Register(&sveltekitDetector{})
|
||||
fw.Register(&gatsbyDetector{})
|
||||
fw.Register(&remixDetector{})
|
||||
fw.Register(&astroDetector{})
|
||||
}
|
||||
|
||||
// nextjsDetector detects Next.js framework.
|
||||
@@ -159,3 +160,32 @@ func (d *remixDetector) Detect(body string, headers http.Header) (float32, strin
|
||||
}
|
||||
return confidence, version
|
||||
}
|
||||
|
||||
// astroDetector detects Astro framework.
|
||||
type astroDetector struct{}
|
||||
|
||||
func (d *astroDetector) Name() string { return "Astro" }
|
||||
|
||||
func (d *astroDetector) Signatures() []fw.Signature {
|
||||
return []fw.Signature{
|
||||
{Pattern: `<meta name="generator" content="Astro`, Weight: 0.5},
|
||||
{Pattern: "astro-island", Weight: 0.5},
|
||||
{Pattern: "data-astro-cid-", Weight: 0.4},
|
||||
{Pattern: "/_astro/", Weight: 0.4},
|
||||
{Pattern: "data-astro-transition", Weight: 0.3},
|
||||
{Pattern: "data-astro-reload", Weight: 0.3},
|
||||
{Pattern: "data-astro-history", Weight: 0.3},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *astroDetector) Detect(body string, headers http.Header) (float32, string) {
|
||||
base := fw.NewBaseDetector(d.Name(), d.Signatures())
|
||||
score := base.MatchSignatures(body, headers)
|
||||
confidence := sigmoidConfidence(score)
|
||||
|
||||
var version string
|
||||
if confidence > 0.5 {
|
||||
version = fw.ExtractVersionOptimized(body, d.Name()).Version
|
||||
}
|
||||
return confidence, version
|
||||
}
|
||||
|
||||
@@ -149,6 +149,11 @@ func init() {
|
||||
"Ghost": {
|
||||
{`Ghost[/\s]+[Vv]?(\d+\.\d+(?:\.\d+)?)`, 0.9, "explicit version"},
|
||||
},
|
||||
"Astro": {
|
||||
{`<meta name="generator" content="Astro v?(\d+\.\d+(?:\.\d+)?)"`, 0.95, "generator meta"},
|
||||
{`Astro[/\s]+[Vv]?(\d+\.\d+(?:\.\d+)?)`, 0.9, "explicit version"},
|
||||
{`"astro":\s*"[~^]?(\d+\.\d+(?:\.\d+)?)"`, 0.85, "package.json"},
|
||||
},
|
||||
}
|
||||
|
||||
// Compile all patterns
|
||||
|
||||
Reference in New Issue
Block a user