Skip to content

fix: filter out security holding packages from Algolia results#2026

Merged
serhalp merged 6 commits intomainfrom
shuuji3/fix/filter-out-security-holding-packages
Apr 20, 2026
Merged

fix: filter out security holding packages from Algolia results#2026
serhalp merged 6 commits intomainfrom
shuuji3/fix/filter-out-security-holding-packages

Conversation

@shuuji3
Copy link
Copy Markdown
Member

@shuuji3 shuuji3 commented Mar 10, 2026

🔗 Linked issue

resolves #2002

🧭 Context

Algoria search returns packages already takendown by npm registory and marked as "Security holding package".

📚 Description

{
	"results": [
		{
			"hits": [
				{
					"name": "dowload_ebok_grundkurs_kunstliche_intelligenz_by_wolfgang_ertel_r9sfy",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1758520468387,
					"owners": [],
					"objectID": "dowload_ebok_grundkurs_kunstliche_intelligenz_by_wolfgang_ertel_r9sfy"
				},
				{
					"name": "dowload_ebok_farouche_atalante_by_emilie_druilhe_nx2bj",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1725351874194,
					"owners": [],
					"objectID": "dowload_ebok_farouche_atalante_by_emilie_druilhe_nx2bj"
				},
				{
					"name": "dowload_ebok_everything_in_between_a_rocker_romance_by_melissa_toppen_fp7ge",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1725351869604,
					"owners": [],
					"objectID": "dowload_ebok_everything_in_between_a_rocker_romance_by_melissa_toppen_fp7ge"
				},
				{
					"name": "dowload_ebok_englens_spil_by_carlos_ruiz_zafon_iben_hasselbalch_lqvq8",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1745588033919,
					"owners": [],
					"objectID": "dowload_ebok_englens_spil_by_carlos_ruiz_zafon_iben_hasselbalch_lqvq8"
				},
				{
					"name": "dowload_ebok_before_dawn_vampire_fallen_book_1_by_morgan_rice_fjwc4",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1762128250838,
					"owners": [],
					"objectID": "dowload_ebok_before_dawn_vampire_fallen_book_1_by_morgan_rice_fjwc4"
				},
				{
					"name": "dowload_ebok_a_guerra_de_hitler_e_o_horror_do_holocausto_by_scott_s_f_meaker_k644u",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1762128244458,
					"owners": [],
					"objectID": "dowload_ebok_a_guerra_de_hitler_e_o_horror_do_holocausto_by_scott_s_f_meaker_k644u"
				},
				{
					"name": "dowload_ebok_a_bela_e_a_fera_by_elizabeth_rudnick_evan_spiliotopoulos_stephen_ch_9ooey",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1745588028183,
					"owners": [],
					"objectID": "dowload_ebok_a_bela_e_a_fera_by_elizabeth_rudnick_evan_spiliotopoulos_stephen_ch_9ooey"
				},
				{
					"name": "dowload_ebok_1917_une_passion_russe_by_max_gallo_d2xeh",
					"downloadsLast30Days": 0,
					"downloadsRatio": 0,
					"popular": false,
					"version": "0.0.1-security",
					"description": "security holding package",
					"repository": {
						"type": "git",
						"url": "npm/security-holder",
						"project": "security-holder",
						"user": "npm",
						"host": "github.com",
						"path": "",
						"branch": "master"
					},
					"deprecated": false,
					"isDeprecated": false,
					"homepage": null,
					"license": null,
					"keywords": [],
					"modified": 1758520462981,
					"owners": [],
					"objectID": "dowload_ebok_1917_une_passion_russe_by_max_gallo_d2xeh"
				}
			],
			"nbHits": 28,
			"offset": 20,
			"length": 8,
			"exhaustiveNbHits": false,
			"exhaustiveTypo": false,
			"exhaustive": {
				"nbHits": false,
				"typo": false
			},
			"query": "download_ebook",
			"params": "query=download_ebook&offset=20&length=8&analyticsTags=%5B%22npmx.dev%22%5D&attributesToRetrieve=%5B%22name%22%2C%22version%22%2C%22description%22%2C%22modified%22%2C%22homepage%22%2C%22repository%22%2C%22owners%22%2C%22downloadsLast30Days%22%2C%22downloadsRatio%22%2C%22popular%22%2C%22keywords%22%2C%22deprecated%22%2C%22isDeprecated%22%2C%22license%22%5D&attributesToHighlight=%5B%5D",
			"index": "npm-search",
			"processingTimeMS": 27,
			"processingTimingsMS": {
				"_request": {
					"roundTrip": 5
				},
				"fetch": {
					"query": 17,
					"scanning": 6,
					"total": 24
				},
				"getIdx": {
					"load": {
						"total": 1
					},
					"total": 1
				},
				"total": 27
			},
			"serverTimeMS": 28
		}
	]
}

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Apr 18, 2026 3:25am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Apr 18, 2026 3:25am
npmx-lunaria Ignored Ignored Apr 18, 2026 3:25am

Request Review

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Security holding packages are now excluded from search results.

Walkthrough

The search page's visibleResults computation now excludes packages flagged as security-held (checks r.package.isSecurityHeld) before applying optional platform-specific filtering. Algolia hits fetch isSecurityHeld, it's mapped into search results, and a new NpmSearchRepository type plus repository? on packages were added.

Changes

Cohort / File(s) Summary
Search page logic
app/pages/search.vue
Added exclusion of results where r.package.isSecurityHeld in visibleResults (applied before platform-specific filtering); updated comment to reflect security-holding filtering.
Algolia mapping & retrieval
app/composables/npm/useAlgoliaSearch.ts
Added isSecurityHeld to AlgoliaHit and to ATTRIBUTES_TO_RETRIEVE; mapped hit.isSecurityHeld into the returned NpmSearchResult.package.
Types: npm registry
shared/types/npm-registry.ts
Introduced new NpmSearchRepository type and added optional repository?: NpmSearchRepository to NpmSearchPackage interface (no behavioural changes).
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarises the main change: filtering out security holding packages from Algolia search results.
Description check ✅ Passed The description is directly related to the changeset, providing context about security holding packages returned by Algolia and the filtering solution.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #2002 to filter out security holding packages from Algolia results using the isSecurityHeld flag.
Out of Scope Changes check ✅ Passed All changes are scoped to the security holding package filtering objective: type definitions for repository metadata, Algolia attribute mapping, and search result filtering logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch shuuji3/fix/filter-out-security-holding-packages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 65f69d54-52bc-488d-b015-3fdff1716d6b

📥 Commits

Reviewing files that changed from the base of the PR and between 3712560 and e0d8779.

📒 Files selected for processing (1)
  • app/pages/search.vue

Comment thread app/pages/search.vue Outdated
@alexdln
Copy link
Copy Markdown
Member

alexdln commented Mar 12, 2026

@shuuji3 Maybe it's better to check only repository.url !== "npm/security-holder"?

@shuuji3
Copy link
Copy Markdown
Member Author

shuuji3 commented Mar 13, 2026

@alexdln Right, probably that's simpler and rubust. I thought repository information might not exist, but I now thing it's unlikely in this case.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
shared/types/npm-registry.ts (1)

316-328: Consider making non-essential fields optional for robustness against API variations.

The NpmSearchRepository interface currently marks all fields as required, but these fields originate from the Algolia API where responses may be incomplete. Additionally, the fields project, user, host, path, and branch are not accessed anywhere in the codebase, suggesting they are either unused or conditionally present in API responses.

Making non-essential fields optional aligns with defensive coding practices for external API types and prevents potential type mismatches if Algolia returns partial repository data. The type: 'git' literal may also be overly restrictive should npm support additional VCS types in future.

♻️ Suggested change
 export interface NpmSearchRepository {
-  type: 'git'
+  type?: string
   url: string
-  project: string
-  user: string
-  host: string
-  path: string
-  branch: string
+  project?: string
+  user?: string
+  host?: string
+  path?: string
+  branch?: string
 }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b673ac2a-7dfa-4a1e-99d0-9f28e7f33e93

📥 Commits

Reviewing files that changed from the base of the PR and between 78c7afb and 42555f9.

📒 Files selected for processing (2)
  • app/pages/search.vue
  • shared/types/npm-registry.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/pages/search.vue

@serhalp serhalp changed the title fix: filter out security holding packages from algoria result fix: filter out security holding packages from Algolia results Mar 14, 2026
@serhalp
Copy link
Copy Markdown
Member

serhalp commented Mar 14, 2026

@shuuji3 🤔 hmm, it doesn't seem to be filtering them out. in any case, maybe we should add test coverage for this?

@shuuji3 shuuji3 marked this pull request as draft March 16, 2026 13:07
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/composables/npm/useAlgoliaSearch.ts (1)

37-54: 🛠️ Refactor suggestion | 🟠 Major

Make isSecurityHeld optional at the Algolia boundary for defensive typing.

NpmSearchPackage.isSecurityHeld is optional, and external API boundaries should be typed defensively. Change AlgoliaHit.isSecurityHeld to optional, but preserve the direct assignment in the mapping to maintain both true and false values as verified by tests.

♻️ Corrected adjustment
 interface AlgoliaHit {
@@
-  isSecurityHeld: boolean
+  isSecurityHeld?: boolean
 }

Keep the mapping as: isSecurityHeld: hit.isSecurityHeld

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/composables/npm/useAlgoliaSearch.ts` around lines 37 - 54, The Algolia
interface should be defensive: change the AlgoliaHit interface's isSecurityHeld
property to optional (isSecurityHeld?: boolean) so it matches upstream
NpmSearchPackage typing, and keep the existing mapping that assigns the value
directly (e.g., isSecurityHeld: hit.isSecurityHeld) so both true and false
values are preserved by the conversion logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/composables/npm/useAlgoliaSearch.ts`:
- Around line 37-54: The Algolia interface should be defensive: change the
AlgoliaHit interface's isSecurityHeld property to optional (isSecurityHeld?:
boolean) so it matches upstream NpmSearchPackage typing, and keep the existing
mapping that assigns the value directly (e.g., isSecurityHeld:
hit.isSecurityHeld) so both true and false values are preserved by the
conversion logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 996c8a45-6d56-4a83-bc72-973d9b8d9d23

📥 Commits

Reviewing files that changed from the base of the PR and between 42555f9 and b70fad2.

📒 Files selected for processing (2)
  • app/composables/npm/useAlgoliaSearch.ts
  • app/pages/search.vue
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/pages/search.vue

@shuuji3
Copy link
Copy Markdown
Member Author

shuuji3 commented Apr 18, 2026

I found that Algoria API actually has the exact attribute for the security holding pakcages called isSecurityHeld so there was no need to implement ourselves. I abondoned my initial implementation and change to include that attribute in the API response.

I also added tests for useAlgoliaSearch composable.

@shuuji3 shuuji3 requested review from alexdln and serhalp April 18, 2026 06:29
Copy link
Copy Markdown
Member

@serhalp serhalp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, good find!

Comment thread app/pages/search.vue
let objects = raw.objects

// Filter out "Security holding package" packages taken down by npm registry
objects = objects.filter(r => !r.package.isSecurityHeld)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Wouldn't it be preferable to implement this filtering in the useAlgoliaSearch or useGlobalSearch composable? Otherwise we'd still be showing security holding packages in other places we use search today (compare page typeahead) and in the future.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to merge this since it's a somewhat important fix, but I think this is worth considering as a follow-up refactor!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@serhalp Thanks, I think useAlgoliaSearch would be a proper location to add filter since the npm API returns the pre-filtered package list so we can make both consistent. I'll create a follow-up PR when I found time later 🙏🏻

@serhalp serhalp added this pull request to the merge queue Apr 20, 2026
@serhalp serhalp added this to the release: brisk breadcrumb milestone Apr 20, 2026
@github-project-automation github-project-automation bot moved this to Ready in Releases Apr 20, 2026
Merged via the queue into main with commit d8aae4b Apr 20, 2026
24 checks passed
@serhalp serhalp deleted the shuuji3/fix/filter-out-security-holding-packages branch April 20, 2026 01:13
@github-project-automation github-project-automation bot moved this from Ready to Released in Releases Apr 20, 2026
@shuuji3 shuuji3 linked an issue Apr 20, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Released

Development

Successfully merging this pull request may close these issues.

⚠️ Algolia search returns malicious/dangerous packages removed from npm registry search

3 participants