Skip to content

[604] Refactor footer to use dynamic CMS content - #221

Merged
VitalyyP merged 3 commits into
mainfrom
604-refactor/footer-dynamic-content
Aug 29, 2025
Merged

[604] Refactor footer to use dynamic CMS content#221
VitalyyP merged 3 commits into
mainfrom
604-refactor/footer-dynamic-content

Conversation

@VitalyyP

Copy link
Copy Markdown
Contributor
  • replaced comAddress field with companyMission and reorganized footer field structure
  • updated SCSS classes from sf-footer__top to sf-footer__mission and improved responsive behavior
  • converted hardcoded footer content to dynamic rendering using global module data

@VitalyyP VitalyyP self-assigned this Aug 26, 2025
@github-actions

github-actions Bot commented Aug 26, 2025

Copy link
Copy Markdown

🔍 Vulnerabilities of apostrophe-cms:test

📦 Image Reference apostrophe-cms:test
digestsha256:2b64e89ccbf5cbd995190f76f73e4f79fd401f23eeb396195833c7d69a6ee4a8
vulnerabilitiescritical: 1 high: 4 medium: 0 low: 0
platformlinux/amd64
size291 MB
packages984
📦 Base Image node:23-alpine
also known as
  • 23-alpine3.22
  • 23.11-alpine
  • 23.11-alpine3.22
  • 23.11.1-alpine
  • 23.11.1-alpine3.22
digestsha256:b9d38d589853406ff0d4364f21969840c3e0397087643aef8eede40edbb6c7cd
vulnerabilitiescritical: 0 high: 0 medium: 1 low: 3
critical: 1 high: 0 medium: 0 low: 0 form-data 4.0.2 (npm)

pkg:npm/form-data@4.0.2

critical 9.4: CVE--2025--7783 Use of Insufficiently Random Values

Affected range>=4.0.0
<4.0.4
Fixed version4.0.4
CVSS Score9.4
CVSS VectorCVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
EPSS Score0.024%
EPSS Percentile5th percentile
Description

Summary

form-data uses Math.random() to select a boundary value for multipart form-encoded data. This can lead to a security issue if an attacker:

  1. can observe other values produced by Math.random in the target application, and
  2. can control one field of a request made using form-data

Because the values of Math.random() are pseudo-random and predictable (see: https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f), an attacker who can observe a few sequential values can determine the state of the PRNG and predict future values, includes those used to generate form-data's boundary value. The allows the attacker to craft a value that contains a boundary value, allowing them to inject additional parameters into the request.

This is largely the same vulnerability as was recently found in undici by parrot409 -- I'm not affiliated with that researcher but want to give credit where credit is due! My PoC is largely based on their work.

Details

The culprit is this line here: https://github.com/form-data/form-data/blob/426ba9ac440f95d1998dac9a5cd8d738043b048f/lib/form_data.js#L347

An attacker who is able to predict the output of Math.random() can predict this boundary value, and craft a payload that contains the boundary value, followed by another, fully attacker-controlled field. This is roughly equivalent to any sort of improper escaping vulnerability, with the caveat that the attacker must find a way to observe other Math.random() values generated by the application to solve for the state of the PRNG. However, Math.random() is used in all sorts of places that might be visible to an attacker (including by form-data itself, if the attacker can arrange for the vulnerable application to make a request to an attacker-controlled server using form-data, such as a user-controlled webhook -- the attacker could observe the boundary values from those requests to observe the Math.random() outputs). A common example would be a x-request-id header added by the server. These sorts of headers are often used for distributed tracing, to correlate errors across the frontend and backend. Math.random() is a fine place to get these sorts of IDs (in fact, opentelemetry uses Math.random for this purpose)

PoC

PoC here: https://github.com/benweissmann/CVE-2025-7783-poc

Instructions are in that repo. It's based on the PoC from https://hackerone.com/reports/2913312 but simplified somewhat; the vulnerable application has a more direct side-channel from which to observe Math.random() values (a separate endpoint that happens to include a randomly-generated request ID).

Impact

For an application to be vulnerable, it must:

  • Use form-data to send data including user-controlled data to some other system. The attacker must be able to do something malicious by adding extra parameters (that were not intended to be user-controlled) to this request. Depending on the target system's handling of repeated parameters, the attacker might be able to overwrite values in addition to appending values (some multipart form handlers deal with repeats by overwriting values instead of representing them as an array)
  • Reveal values of Math.random(). It's easiest if the attacker can observe multiple sequential values, but more complex math could recover the PRNG state to some degree of confidence with non-sequential values.

If an application is vulnerable, this allows an attacker to make arbitrary requests to internal systems.

critical: 0 high: 1 medium: 0 low: 0 linkifyjs 4.2.0 (npm)

pkg:npm/linkifyjs@4.2.0

high 8.8: CVE--2025--8101 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

Affected range<4.3.2
Fixed version4.3.2
CVSS Score8.8
CVSS VectorCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N
EPSS Score0.065%
EPSS Percentile21st percentile
Description

Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') vulnerability in Linkify (linkifyjs) allows XSS Targeting HTML Attributes and Manipulating User-Controlled Variables.This issue affects Linkify: from 4.3.1 before 4.3.2.

critical: 0 high: 1 medium: 0 low: 0 connect-multiparty 2.2.0 (npm)

pkg:npm/connect-multiparty@2.2.0

high 7.8: CVE--2022--29623 Unrestricted Upload of File with Dangerous Type

Affected range<=2.2.0
Fixed versionNot Fixed
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.320%
EPSS Percentile54th percentile
Description

An arbitrary file upload vulnerability in the file upload module of Express Connect-Multiparty 2.2.0 allows attackers to execute arbitrary code via a crafted PDF file. NOTE: the Supplier has not verified this vulnerability report.

critical: 0 high: 1 medium: 0 low: 0 async 0.9.2 (npm)

pkg:npm/async@0.9.2

high 7.8: CVE--2021--43138 OWASP Top Ten 2017 Category A9 - Using Components with Known Vulnerabilities

Affected range<2.6.4
Fixed version2.6.4, 3.2.2
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.907%
EPSS Percentile75th percentile
Description

A vulnerability exists in Async through 3.2.1 (fixed in 3.2.2), which could let a malicious user obtain privileges via the mapValues() method.

critical: 0 high: 1 medium: 0 low: 0 async 1.5.2 (npm)

pkg:npm/async@1.5.2

high 7.8: CVE--2021--43138 OWASP Top Ten 2017 Category A9 - Using Components with Known Vulnerabilities

Affected range<2.6.4
Fixed version2.6.4, 3.2.2
CVSS Score7.8
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Score0.907%
EPSS Percentile75th percentile
Description

A vulnerability exists in Async through 3.2.1 (fixed in 3.2.2), which could let a malicious user obtain privileges via the mapValues() method.

@VitalyyP
VitalyyP enabled auto-merge (squash) August 26, 2025 09:03
@coderabbitai

coderabbitai Bot commented Aug 26, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

  • Replaces the public field comAddress with companyMission and removes footerForm in website/modules/@apostrophecms/global/index.js; Footer group fields become ['companyMission', 'footerLinks', 'socialMediaLinks'].
  • Renames .sf-footer__top to .sf-footer__mission, removes .sf-footer__tagline in favor of p selectors, adds responsive centering, and introduces gaps and updated hover/focus styles in website/modules/asset/ui/src/scss/_footer.scss.
  • Updates website/views/fragments/fragments.html to render companyMission, socialMediaLinks, and footerLinks dynamically (conditional rendering, dynamic link URL/target resolution) and removes previously hard-coded tagline and static social/privacy link.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • vasilyyaremchuk
  • killev
  • Anton-88

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3b1d491 and 7c6cc0d.

📒 Files selected for processing (1)
  • website/views/fragments/fragments.html (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/views/fragments/fragments.html
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e-tests
  • GitHub Check: unit-tests
  • GitHub Check: lint
  • GitHub Check: security-scan
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 604-refactor/footer-dynamic-content

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (6)
website/modules/@apostrophecms/global/index.js (2)

100-112: Footer links schema: solid; consider naming consistency.
Implementation mirrors social links and correctly reuses linkSchema. Minor nit: SMLink (camel-cased acronym) vs footerLink (lower camel) is inconsistent. Consider SMLink → socialLink (or footerLink → FooterLink) for consistency across array item keys.


128-129: Reorder footer fields to match rendered order in the template.
In fragments.html, social links render before footer links. Reordering the group improves editor UX by aligning authoring order with display order.

Apply this diff:

-        fields: ['companyMission', 'footerLinks', 'socialMediaLinks'],
+        fields: ['companyMission', 'socialMediaLinks', 'footerLinks'],
website/modules/asset/ui/src/scss/_footer.scss (2)

26-46: Scope margin-right to the inline layout and keep mobile truly block-level.
Right margin on block paragraphs is unnecessary on mobile and can create accidental horizontal spacing. Move margin-right into the medium breakpoint when paragraphs become inline-block.

Apply this diff:

     p {
       font-size: $font-size-footer-mobile;
       font-weight: $font-weight-300;
       color: $gray-300;
       margin: 0;
       line-height: 120%;
       display: block;
-      margin-right: 4px;
       text-wrap: balance;
 
       &:first-child {
         display: block;
       }
 
       &:not(:first-child) {
         display: block;
         @include breakpoint-medium {
           display: inline-block;
+          margin-right: 4px;
         }
       }
     }

78-90: Keyboard focus: add a visible focus style.
You already underline on :focus; adding :focus-visible improves clarity for keyboard users without affecting mouse users.

Apply this diff:

   .sf-footer__links-item {
     font-size: $font-size-footer-mobile;
     font-weight: $font-weight-normal;
     color: $gray-500;
     text-decoration: none;
     transition: color 0.2s ease;
 
     &:hover,
     &:focus {
       color: $gray-400;
       text-decoration: underline;
     }
+
+    &:focus-visible {
+      outline: 2px solid $gray-400;
+      outline-offset: 2px;
+      text-decoration: underline;
+    }
   }
website/views/fragments/fragments.html (2)

43-56: Dynamic social links: good use of target protection; consider optional a11y label.
href resolution and noopener/noreferrer are handled correctly. Optional: wrap this group in a nav with aria-label="Social" for clearer landmarks.

Example (no diff required):


57-70: Dynamic footer links: consistent with social; same optional a11y improvement applies.
Semantics are fine; you may optionally use a nav with aria-label="Footer links" or a list for assistive tech grouping.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f77f83b and 3b1d491.

📒 Files selected for processing (3)
  • website/modules/@apostrophecms/global/index.js (3 hunks)
  • website/modules/asset/ui/src/scss/_footer.scss (2 hunks)
  • website/views/fragments/fragments.html (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-26T15:57:01.766Z
Learnt from: yuramax
PR: speedandfunction/website#121
File: website/modules/asset/ui/src/scss/_vacancies.scss:99-102
Timestamp: 2025-05-26T15:57:01.766Z
Learning: In website/modules/asset/ui/src/scss/_vacancies.scss, the margin shorthand (e.g., `margin: 0 0 8px`) in `.sf-vacancies_footer h2` is intentionally used to reset all margins and set specific bottom margins, rather than using `margin-bottom` alone. This approach ensures clean baseline styling that doesn't inherit unwanted margins, while still allowing the sibling selector `.vacancy-card + .sf-vacancies_footer h2` to add top margins when a vacancy card precedes the footer.

Applied to files:

  • website/modules/asset/ui/src/scss/_footer.scss
🧬 Code graph analysis (1)
website/modules/@apostrophecms/global/index.js (2)
website/modules/links-buttons-widget/index.js (1)
  • linkSchema (2-2)
website/modules/buttons-widget/index.js (1)
  • linkSchema (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: sonarqube
  • GitHub Check: lint
  • GitHub Check: e2e-tests
  • GitHub Check: security-scan
🔇 Additional comments (5)
website/modules/@apostrophecms/global/index.js (1)

75-86: Company mission area looks good; constrained widget set is appropriate.
Using a single rich-text widget with a shared heading toolbar keeps the mission copy tidy and consistent.

website/modules/asset/ui/src/scss/_footer.scss (2)

15-25: Mission block centering: LGTM.
fit-content with auto margins is a clean way to center the mission on medium+ without impacting mobile.


15-46: No remaining legacy footer classes found
I’ve searched the entire repository—including SCSS, HTML, JS/JSX, TSX, and Vue files—for sf-footer__top and sf-footer__tagline and found no occurrences. All markup appears to have been migrated to .sf-footer__mission. You can safely remove the old styles and proceed with merging.

website/views/fragments/fragments.html (2)

34-41: Mission area: correct conditional rendering.
Area check guards against empty content and aligns with the new .sf-footer__mission structure.


46-51: Confirmed: customUrl is safely sanitized by Apostrophe’s built-in URL field type
Apostrophe’s type: 'url' field automatically “launders” common XSS attack vectors and only permits the following schemes by default: http, https, ftp, and mailto. Any other protocols (including javascript: or data:) are discarded by the sanitizer before rendering (docs.apostrophecms.org)

Comment thread website/views/fragments/fragments.html Outdated
@VitalyyP
VitalyyP requested a review from Anton-88 August 26, 2025 23:26

@Anton-88 Anton-88 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@sonarqubecloud

Copy link
Copy Markdown

@VitalyyP
VitalyyP disabled auto-merge August 29, 2025 12:18
@VitalyyP
VitalyyP merged commit d89fc55 into main Aug 29, 2025
12 checks passed
@VitalyyP
VitalyyP deleted the 604-refactor/footer-dynamic-content branch August 29, 2025 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants